OmniAICreator/Qiita-1.07M huggingface dataset:
AtCoder Beginner Contest 135 A

C++の基本的なところ、本読むより実際に書いた方が覚えられそうなので練習する。

[https://atcoder.jp/contests/abc135/tasks/abc135_a:title]

<!-- more -->

### 最初に書いたコード

```
#include<iostream>
#include<string>
using namespace std;

int main() {
  int n, m;
  string message = "IMPOSSIBLE";
  cin >> n >> m;
  if ((n + m) % 2 == 0) {
    cout << (n + m) / 2 << endl;
  } else {
    cout << message << endl;
  }
}
```

### 他の回答をみて修正したコード

```
#include<iostream>
#include<string>
using namespace std;

int main() {
  int n, m;
  string message = "IMPOSSIBLE";
  cin >> n >> m;
  if ((n + m) & 1) cout << message << endl;
  else cout << (n + m) / 2 << endl;
}
```

### 学んだこと
- コンパイルと実行
  - `g++ -o sample sample.cpp && ./sample`
  - `-o`は出力されるファイル（実行ファイル）の名前を指定するオブション

- 文字列はchar型の要素をもつ配列だが、stringというモジュールをincludeするとstring型がつかえるようになる。

- `A ? B :C`でBとCの型は同じでなければならない。

- if文の`{}`は省略できる。

- `&`演算子はビット単位の論理積を返す。
  - `X & 1`とすると、Xの1の位が{0, 1}なら{0, 1}を返す。
  - つまり、2で割った余りを求めるのと同じことができる。

- ガチな方々は自作関数などを大量に用意してたりするので参考にしにくい。

- main関数の戻り値ってなんでintなの？
  - 終了コードを返すから。

- シングルクォーテーションは文字列リテラルを、ダブルクォーテーションは文字列へのポインタを表すらしい（理解が不正確かも）。
AtCoder Beginner Contest 134 C

[https://atcoder.jp/contests/abc134/tasks/abc134_c:title]

<!-- more -->

### コード

```
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

int main() {
  int N;
  cin >> N;
  int A[N];
  int A_sort[N];
  for (int i = 0; i < N; i++) {
    cin >> A[i];
    A_sort[i] = A[i];
  }
  sort(A_sort, A_sort + N);
  for (int i = 0; i < N; i++) {
    int ret;
    if (A[i] == A_sort[N-1]) ret = A_sort[N-2];
    else ret = A_sort[N-1];
    cout << ret << endl;
  }
}
```

### 学んだこと
- std::sortで実際にメモリ上の並び順が変わる。sort前の順番を保持しておきたければ、コピーをつくってsortすること。
- 配列をまるごとコピーする専用の方法は特に用意されていないので、以下でやる。
  - 1要素ずつコピー。
  - memcpy関数でメモリ領域をまとめてコピー。
  - 構造体のメンバとして配列をもたせて、構造体をコピーするとメンバもコピーされる。
- `#include <bits/stdc++.h>`はgccで用意されており、標準ライブラリを一括includeできる。
  - が、macでこれを使うのはちょっと面倒そうなのでやめておく。
AtCoder Beginner Contest 132 A

[https://atcoder.jp/contests/abc132/tasks/abc132_a:title]

<!-- more -->

### 最初に書いたコード

```
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

int main() {
  string s;
  cin >> s;
	
  vector <int> v(4);
  for (int i = 0; i < s.length(); i++) {
    v[i] = s[i];
  }

  sort(v.begin(), v.end());

  string ret;
  if (v[0] == v[1] && v[1] != v[2] && v[2] == v[3]) ret = "Yes";
  else ret = "No";
	
  cout << ret << endl;
}
```

# 他の回答を見て修正したコード

std::sortはstringに対してもつかえる。
(stringもベースは配列なので当然か。)

```
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

int main() {
  string s;
  cin >> s;
	
  sort(s.begin(), s.end());

  string ret;
  ret = (s[0] == s[1] && s[1] != s[2] && s[2] == s[3]) ? "Yes" : "No";
	
  cout << ret << endl;
}
```

### 学んだこと
- std::vectorというのは可変長配列を表現するクラス
  - vectorというヘッダファイルをincludeすることで使用可能になる。
  - 以下の形で宣言する。
    - `vector <要素の型> vct(配列のサイズ);`
    - `vector <要素の型> vct{要素1 要素2 要素3};`
- 可変長配列の他にもリスト、キューなどのデータ構造を表現するクラステンプレートが存在し、コンテナと呼ばれる。
- algorithmというヘッダファイルをincludeすると、std::sortなどの関数がつかえる。
AtCoder Beginner Contest 134 A

[https://atcoder.jp/contests/abc134/tasks/abc134_a:title]

<!-- more -->

### コード

```
#include<iostream>
#include<cmath>
using namespace std;

int main() {
  int r;
  cin >> r;
  cout << 3 * pow(r, 2) << endl;
}
```

### 学んだこと
- cmathというライブラリをincludeすると、べき乗計算のための`std::pow`関数が使える。
AtCoder Beginner Contest 031 B

[https://atcoder.jp/contests/arc031/tasks/arc031_2:title]

<!-- more -->

### コード

自力でACできた！わーい。

```
#include <iostream>
#include <string.h>
using namespace std;

char map[10][10];

// あるmapと出発点が与えられたら、そのmapにおいてその出発点から行けるところを'v'で塗りつぶす関数。
void dfs(int i, int j, char copy[10][10]) {
  if (i < 0 || 10 <= i || j < 0 || 10 <= j || copy[i][j] == 'x' || copy[i][j] == 'v') return;
  if (copy[i][j] == 'o') copy[i][j] = 'v';
  
  dfs(i-1, j, copy);
  dfs(i+1, j, copy);
  dfs(i, j-1, copy);
  dfs(i, j+1, copy);
}

// 実験用のコピーされたmapを受け取り、陸地がひとつづきであるかどうかをT/Fで返す関数。
bool unity(char copy[10][10]) {
  bool ret = true;
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      if (copy[i][j] == 'o') ret = false;
    }
  }
  return ret;
}

int main() {
  // mapを読むこむ
  int start[2] = {-1, -1};
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      cin >> map[i][j];
      if (start[0] == -1 && map[i][j] == 'o') {
        start[0] = i;
        start[1] = j;
      }
    }
  }

  // 出力する文字列を初期化
  string ret = "NO";

  // 海を1箇所につき1ループ
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      if (map[i][j] == 'x') {
        // mapのコピーをつくる
        char copy[10][10];
        memcpy(copy, map, sizeof(map));
        // コピーの中の海を1箇所だけ陸にする
        copy[i][j] = 'o';
        // 陸がひとつづきかどうか確認する
        dfs(start[0], start[1], copy);
        // 陸がひとつづきなら、出力する文字列をYESにする
        if (unity(copy)) ret = "YES";
      }
    }
  }

  cout << ret << endl;
}
```

### 学んだこと
- 色んなところを埋め立ててみて、その都度陸地がひとつづきか調べる。そのときに訪問状況を記録する必要があるが、それは毎回まっさらな状態のマップをつかう必要がある。なので標準入力からつくったマップに直接記録をつくるのではなく、都度訪問情報記録用のマップのコピーをつくる。
- 配列そのものを関数の戻り値にすることはできない。
AtCoder Typical Contest 001 A

[https://atc001.contest.atcoder.jp/tasks/dfs_a:title]

<!-- more -->

### コード

他の回答をみつつ実装した。

```
#include<iostream>
#include<string>
using namespace std;
#define MAX_H 500
#define MAX_W 500
 
int h, w;
char maze[MAX_H][MAX_W];
bool visited[MAX_H][MAX_W];

# i,jを渡すと
# - そこからゴールに行けるならtrueを返す。
# - そこからゴールに行けるならvisited[i][j]をtrueにする。
bool search(int i, int j) {
  # マップの外側ならfalseを返す
  if (i<0 || h<=i || j<0 || w<=j) return false;
  # 壁ならfalseを返す
  if (maze[i][j] == '#') return false;
  # 訪問済みならfalseを返す
  if (visited[i][j]) return false;
  # ゴールならtrueを返す
  if (maze[i][j] == 'g') return true;

  # 訪問済みとしてマークする
  visited[i][j] = true;
 
  # 上下左右について再帰的にsearchを呼び出す
  return(
    search(i - 1, j    ) ||
    search(i + 1, j    ) ||
    search(i    , j - 1) ||
    search(i    , j + 1)
  );
}

int main() {
  # 入力を受け取る
  int start[2];
  cin >> h >> w;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      cin >> maze[i][j];
      # スタートの位置も記録しておく
      if (maze[i][j] == 's') {
        start[0] = i;
        start[1] = j;
      }
      # 配列visitedを初期化しておく
      visited[i][j] = false;
    }
  }

  # 主要な処理
  string ret = (search(start[0], start[1]) == true) ? "Yes" : "No";

  cout << ret << endl;
}
```

### 学んだこと
- 大筋としては単なる再帰なのだが、戻らないようにするために訪問済みかどうかという情報をメモ化しておく必要がある、っていうのがポイント。
- cinで入力を受け取ってcharに入れる場合、ちゃんと1文字ずつ受け取ってくれるみたい。
- `array[i]`は格納された中身を取り出すので、文字列と比較するときは`array[i] == "string"`ではなく`array[i] == 'string'`
- search関数の中でmazeという配列を使わないといけないけど、mazeの大きさが具体的に決まるのはmain関数内で標準入力を受け取ってから。
  - => main関数の外側で予め十分に大きなサイズのmazeという配列をつくっておけばよい！
AtCoder Beginner Contest 131 C

[https://atcoder.jp/contests/abc131/tasks/abc131_c:title]

<!-- more -->

### コード

```
#include<iostream>
using namespace std;

int gcd(int a, int b) {
  if (a < b) {
    int tmp = a; a = b; b = tmp;
  }
  int r = a % b;
  while (r != 0) {
    a = b;
    b = r;
    r = a % b;
  }
  return b;
}

long lcm(long a, long b) {
  return a * b / gcd(a, b);
}

int main() {
  long a, b;
  int c, d;
  cin >> a >> b >> c >> d;
  long div_c   = b/c        - (a-1)/c;
  long div_d   = b/d        - (a-1)/d;
  long div_lcm = b/lcm(c,d) - (a-1)/lcm(c,d);

  cout << (b-a+1) - (div_c + div_d - div_lcm) << endl;
}
```

### 学んだこと
- C++17ではnumericライブラリにstd::lcmなどが用意されている。
  - が、AtCoderで選択できるのはC++14なので、lcmなど自作する必要がある。
- int型は10*9くらいまでしか表せない。もっと大きい整数を表現するにはlong型を使う。
  - デバッグして突然負の値が登場してたら、型から値が溢れていることを疑うべし。
Educational DP Contest A

[https://atcoder.jp/contests/dp/tasks/dp_a:title]

<!-- more -->

[こちらの記事](https://qiita.com/drken/items/dc53c683d6de8aeacf5a)を参考にしつつ練習。

### もらうDP

```
#include<iostream>
using namespace std;

int main() {
  // 入力を受け取る
  int n;
  cin >> n;
  int h[n], dp[n];
  for (int i=0; i<n; i++) cin >> h[i];

  // 最初2つを記録
  dp[0] = 0;
  dp[1] = abs(h[1] - h[0]);

  // 最初2つをもとに、前の2つから情報をもらってdpを記録していく
  for (int i=2; i<n; i++) {
      dp[i] = min(
          dp[i-2] + abs(h[i-2] - h[i]),
          dp[i-1] + abs(h[i-1] - h[i])
      );
  }

  cout << dp[n-1] << endl;
}
```

### 配るDP

```
#include<iostream>
using namespace std;

const int INF = 1 << 30

int main() {
  // 入力を受け取る
  int n;
  cin >> n;
  int h[n], dp[n];
  for (int i=0; i<n; i++) {
    cin >> h[i];
    dp[i] = INF;
  }

  // 最初1つを記録
  dp[0] = 0;

  // 最初1つをもとに、後ろ2つのdpを記録していく
  for (int i = 0; i < n; i++) {
    dp[i+1] = min(dp[i+1], dp[i] + abs(h[i+1]- h[i]));
    dp[i+2] = min(dp[i+2], dp[i] + abs(h[i+2]- h[i]));
  }

  cout << dp[n-1] << endl;
}
```

### メモ化再帰

```
#include<iostream>
#include<cmath>
using namespace std;

const int INF = 1 << 30;
int h[100000];
int dp[100000];

// i番目の足場に行くまでの最小コストを返す関数
int rec(int i) {
  // メモされていたらメモされた値を返す
  if (dp[i] < INF) return dp[i];

  // i = 0 なら明示的に値を返す
  if (i == 0) return 0;

  // 再帰的にrecを呼び出す
  int ret = min(
    rec(i-1) + abs(h[i] - h[i-1]),
    i != 1 ? rec(i-2) + abs(h[i] - h[i-2]) : INF
  );

  // 結果をメモする
  dp[i] = ret;
  return ret;
}

int main() {
  // 入力を受け取る
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    cin >> h[i];
    // メモを初期化する
    dp[i] = INF;
  }

  cout << rec(n-1) << endl;
}
```

### 学んだこと
- もらうDP, 配るDP, メモ化再帰という方法を整理して理解できた。
- 定数の宣言は`#define`ではなく`const`をつかうのがベター（defineが文字列の埋め込みであるがゆえのトラブルを避けられる）。
- RuntimeErrorで疑うべきは、ゼロ除算、無限再帰、配列の範囲外アクセス。
  - 無限再帰を疑ってたら、配列固定長の指定誤りという凡ミスによる範囲外アクセス=segmentation errorだった…。
AtCoder Regular Contest 037 B

[https://atcoder.jp/contests/arc037/tasks/arc037_b:title]

<!-- more -->

### コード

他の回答をみつつ書いた。

```
#include<iostream>
#include<vector>
using namespace std;
#define MAX_N 100

vector<int> graph[MAX_N];
bool visited[MAX_N];

// あるノードiと1つ前に訪れたノードprevを渡すと
// - iから行けるノードを全て配列visitedに記録する
// - iから行けるパスが閉路をもっていればfalseを、閉路をもっていなければtrueを返す。
bool dfs(int i, int prev) {

  // 既に訪れられているノードなら、falseを返す（閉区間であることを表す）
  if (visited[i]) return false;

  // 訪問済みとしてマークする
  visited[i] = true;

  bool ret = true;
  // 隣接するノードのうち、
  for (int j = 0; j < graph[i].size(); j++) {
    // 1つ前に訪れたノード以外について、
    if (graph[i][j] == prev) continue;
    else {
      // 再帰的にdfsを呼び出す
      if (!dfs(graph[i][j], i)) ret = false;      
    }
  }
  return ret;
}

int main() {

  // ノードとエッジの数を入力から受け取る
  int N, M;
  cin >> N >> M;

  // 訪問状況を表す配列を初期化する
  for (int i = 0; i < N; i++) {
    visited[i] = false;
  }

  // 入力から隣接リストを作成する
  int u, v;
  for (int i = 0; i < M; i++) {
    cin >> u >> v;
    graph[u-1].push_back(v-1);
    graph[v-1].push_back(u-1);
  }

  // ノード1つにつき1ループする
  int count = 0;
  for (int i; i < N; i++) {
    // もし訪問済みでないならば
    if (!visited[i]) {
      // そのノードを起点としてdfsを呼び出す
      if (dfs(i, -1)) count++;
    }
  }

  cout << count << endl;
}
```

### 学んだこと
- グラフはオブジェクトにより表現することもできなくはないが、隣接リスト・隣接行列の方が利点が多いようだ。今回は隣接リストをつかった。
- (要素数, 値)みたいな初期化の仕方は、std::vectorでしか見当たらず、配列やstd::arrayでは見当たらない。
  - 配列やstd::arrayで全要素を同じ値で初期化するには、for文を書く必要がありそう。
StructとOpenStruct

似た名前だが意外と挙動が異なるな、と思ったのでメモ。

<!-- more -->

# Struct

```
# クラスをつくる
> Man = Struct.new(:age, :sex)  # => Man
> Man.class  # => Class

# クラスからインスタンスをつくる
> taro = Man.new(28, :male)  # => #<struct Man age=28, sex=:male>
> taro.class  # => Man

# 定義した属性を利用できる
> taro.age += 1
> taro.age  # => 29

# 定義していない属性は利用できない
> taro.job = :engineer  # NoMethodError: undefined method `job=' for #<struct Man age=28, sex=:male>
```

# OpenStruct

```
# コアライブラリではなく標準ライブラリ
> require 'ostruct'

# newするとシンプルにOpenClassインスタンスが返ってくる
> taro = OpenStruct.new({age: 28, sex: :male})  # => #<OpenStruct age=28, sex=:male>
> taro.class  # => OpenStruct

# 定義した属性を利用できる
> taro.age += 1
> taro.age  # => 28

# 定義していなかった属性も利用できる
> taro.job = :engineer  # => :engineer
> taro.job  # => :engineer
```

# 違い

「最初に定義してない属性を利用できる/できない」というのはStruct/OpenStructという名前から想像できたので問題なし。

意外だったのは以下の違い。

- Struct.newではClassインスタンス(ex. Man)がつくられる => そのクラスからインスタンス(ex. taro)をつくる
  - 最も具体的なオブジェクトを生成するまでに2段階を要する。
  - 普通にクラスを定義している感覚。
- OpenStruct.newではいきなりOpenStructインスタンスがつくられる
  - 最も具体的なオブジェクトを生成するまでに1段階のみ要する。
  - クラス定義というよりは、ハッシュを生成している感覚。
  - (Hashとの最大の違いは、メソッドをもたせられることかな？たぶん)
x_evalしたときのコンテクスト(続)

前回x_evalメソッドでのコンテクストについて、selfとklassという側面からまとめた。((https://tamani.hatenadiary.jp/entry/2019/08/04/135257))

今回はローカル変数の状態という側面を加えて、x_eval/x_execメソッドでのコンテクストについておさらいする。
<!-- more -->
# x_eval/x_exec実行時のローカル変数の状態

単純な話で、ローカル変数の状態は呼び出し元のまま。

```
class Sample; end
sample = Sample.new

var = "top level"

# eval系メソッド

Sample.class_eval("p var")     # => "top level"
Sample.class_eval{ p var }     # => "top level"

Sample.instance_eval("p var")  # => "top level"
Sample.instance_eval{ p var }  # => "top level"

sample.instance_eval("p var")  # => "top level"
sample.instance_eval{ p var }  # => "top level"

# exec系メソッド

Sample.class_exec{ p var }     # => "top level"

Sample.instance_exec{ p var }  # => "top level"

sample.instance_exec{ p var }  # => "top level"
```

# コンテクストまとめ

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vSo3mI8NqH_hw-v8MQnbYOqNU9EuWf4yiIDriPILVl6dMvK4p84PJ8FPxblHpGTFD5mSIEXHhHOU842/embed?start=false&loop=false&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
x_evalしたときのコンテクスト

# コンテクスト

「コンテキストとはおおざっぱに言えばローカル変数の状態、self, klassから成る。」((https://blog.yugui.jp/entry/547))
<!-- more -->
- 「ローカル変数というのは、参照できる限り外側のスコープも含めた全部だ。」
- 「selfというのはデフォルトでメソッドを受け取る相手である。」
- 「klassとは『今メソッドを定義したらどこに定義されるか』というクラスである。」((https://blog.yugui.jp/entry/558))

ローカル変数の状態は措いておき、selfとklassについて確認していく。

サンプルコードでは以下を前提とする。

```
class Sample; end
sample = Sample.new
```

# シンプルなクラス定義での話

### Sampleのクラス定義内

```
class Sample
  p self  # => Sample
  def m1; end
end

Sample.new.method(:m1).owner  # => Sample
```

Sampleのクラス定義内ではselfもklassもSampleである。

### Sampleの特異クラス定義内

```
class << Sample
  p self  # => #<Class:Sample>
  def m2; end
end

Sample.method(:m2).owner  # => #<Class:Sample>
```

Sampleの特異クラス定義内ではselfもklassもSampleの特異クラスである。

### sampleの特異クラス定義内

```
class << sample
  p self  # => #<Class:#<Sample:0x007fc71aa74f98>>
  def m3; end
end

sample.method(:m3).owner  # => #<Class:#<Sample:0x007fc71aa74f98>>
```

sampleの特異クラス定義内ではselfもklassもsampleの特異クラスである。

# x_evalをつかったときの話

### class_eval

```
Sample.class_eval do
  p self  # => Sample
  def m4; end
end

sample.method(:m4).owner  # => Sample
```

selfもklassも、レシーバ(Sample)となる。

これはSampleのクラス定義内のコンテクストと同一である。

### instance_eval

```
Sample.instance_eval do
  p self  # => Sample
  def m5; end
end

Sample.method(:m5).owner  # => #<Class:Sample>
```

```
sample.instance_eval do
  p self  # => #<Sample:0x007fc71aa74f98>
  def m6; end
end

sample.method(:m6).owner  # => #<Class:#<Sample:0x007fc71aa74f98>>
```

selfはレシーバとなり、klassはレシーバの特異クラスとなる。

これはSample/sampleの特異クラス定義内のコンテクストとは下表のとおり異なる。

|    |  x.instance_eval  |    |    xの特異クラス定義内|
|---|---|---|---|
|  self  |  x自体  |  ≠  |   xの特異クラス |
|  klass  |  xの特異クラス  |  =  |  xの特異クラス  |
evalことはじめ

# eval

```
osamu = 'tezuka osamu'  # => "tezuka osamu"
eval('osamu')  # => "tezuka osamu"
<!-- more -->
#  Bindingインスタンスを渡すことでコンテクストを指定できる
def context_literature
  osamu = 'dazai osamu'
  binding
end
eval('osamu', context_literature)  # => "dazai osamu"
```

# instance_eval

文字列やブロックを渡すと、それを「レシーバの特異クラス定義の中に近いコンテクスト」で評価してくれる。

```
# 準備
class Novelist
  attr_reader :works
  def initialize(*works)
    @works = works
  end
end

dazai = Novelist.new("ningen sikkaku", "syayo")
akutagawa = Novelist.new("rashomon", "hana")

# usage1: 文字列を渡す
dazai.instance_eval('def representative_work; @works[0]; end')
dazai.singleton_methods  # => [:representative_work]
dazai.representative_work  # => "ningen sikkaku"

# usage2: ブロックを渡す
akutagawa.instance_eval {def representative_work; @works[0]; end}
akutagawa.singleton_methods  # => [:representative_work]
akutagawa.representative_work  # => "rashomon"
```

# instance_exec

概ねinstance_evalと同じだが、以下の点で異なる。

###### instance_execだとできないこと
 文字列を渡せない

```
dazai.instance_exec('@works << "otogi zoushi"')  # LocalJumpError: no block given
```


###### instance_execでのみできること
引数をブロック引数として渡せる

```
# usage1: 引数なしのブロック(これはinstance_evalでもできる)
dazai.instance_exec{@works << 'otogi zoushi'}
dazai.works  # => ["ningen sikkaku", "syayo", "otogi zoushi"]

# usage2: 引数ありのブロック(これはinstance_evalではできない)
dazai.instance_exec('good bye'){ |work| @works << work }
dazai.works  # => ["ningen sikkaku", "syayo", "otogi zoushi", "good bye"]
```

こういうときにつかえるな！とはまだ想像できないが、instance_execの方が柔軟性が高そうだな？

とりあえずここまで。
LinuxMint19でDockerを使えるようにする

#準備

```
sudo apt-get install apt-transport-https   ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt-get update
```

##dockerのインストール

```
sudo apt-get install docker-ce
sudo apt-get install docker-compose
```

#dockerグループへのuser登録

```
sudo usermod -aG docker $USER
```

#docker起動試験

```
sudo docker run hello-world
```

```
$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:6540fc08ee6e6b7b63468dc3317e3303aae178cb8a45ed3123180328bcc1d20f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
```

どうやら動いたらしい。
bundle install時にmysql2のビルドでエラーが出た時の対処法

Ruby 2.6.3にしてbundle installした時のメモ。

#### opensslをインストール

バージョンは指定なしでも1.1.1cでもどちらでも良いです。

#### bundlerの設定を追加
```
bundle config --global build.mysql2 --with-opt-dir=/usr/local/opt/openssl
```

または

```
bundle config --global build.mysql2 --with-ldflags=-L/usr/local/opt/openssl/lib
```

参考：
https://qiita.com/ffggss/items/2a6e965c8c3133a92eb9
https://qiita.com/HrsUed/items/ca2e0aee6a2402571cf6
ubuntu 18.04版でnodejsとnpmを入れようとしたら　unable to locate package になったときの対策

ubuntu 18.04版でnodeJSをインストールしようとして2時間程使ってしまったので悔しくてメモ

nodejsとnpmを一気にインストールしようとして以下のコマンドを実行した。

```
sudo apt install -y nodejs npm
```

すると以下のようになった

```
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package nodejs
E: Unable to locate package npm
```

###原因
インストール元を指定してあげないとnodejsのみをインストールしてしまってnpm等のパッケージをよしなにインストールしてくれない。

###対策

以下を実行

```
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
```

その後

```
sudo apt install -y nodejs
```
を実行すると問題なくインストールできた

### 補足

nodejsとnpmがインストールできているか確認

```
node --version
npm --version
```

この時点でnpmがインストールできていなければ以下を実行

```
sudo apt-get install -y npm
```

###参考
https://stackoverflow.com/questions/47371904/e-unable-to-locate-package-npm
【HerokuPostgres】HerokuPostgresを立てるには？

# HerokuPostgresを立てる

### 注意点
1. Herokuの無料アカウントは作成済み。
1. Google Chromeで作業実施。
1. リンク先URLに従い、Appを作成していることが前提。

[【Heroku】HerokuでAppを作る] (https://qiita.com/kei1-dev/items/8965afe70a5edeb47890) 

## 1.ダッシュボードからメニュー>Dataを選択。
![NoName_2019-8-10_1-46-57_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/7b2e59f6-702e-bd25-0101-a77978b676fd.png)

## 2.Heroku Postgresの真下のCreate oneを選択。
![NoName_2019-8-10_1-47-14_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/c728542b-543a-3f0e-6f71-f4a15417cf94.png)

## 3. 画面右上にあるInstall Heroku Postgresを選択。
![NoName_2019-8-10_1-48-6_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/fd771e2f-d4a5-063a-3844-52cdcf595643.png)

## 4. すでに作成したAppを選択し、関連付ける。Provision add onを選択。
- Add on PlanがHobby Dev -Freeであることを確認する。
![NoName_2019-8-10_1-48-39_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/5d1e3eb6-aa90-85df-f3c7-51c77dd707c5.png)

## 5. 関連付けたAppのResourcesにDBが作成されていることを確認。
- Resourceの詳細画面からSetting>DatabaseCredentialに接続情報があるので、任意のDB Clientから接続確認する。
![NoName_2019-8-10_1-49-9_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/fb484476-bbd4-58f4-f871-786b48712fab.png)
![NoName_2019-8-10_1-50-4_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/47c051db-c370-e6ca-e5fd-244d712be432.png)

#### IBM CloudからHerokuPostgreに繋いだWordPress立てる予定がうまくいかなかった…
Vue CLI install

### nodejs.org
↓
Vue CLIのnpmパッケージ
↓
npm install -g @vue/cli@3.5.0
↓
vue -V
↓
vue create [name]
↓
npm run serve
↓
vue add vuetify



### nodejs LTS
↓
npm install -g @vue/cli
↓
vue create [project-name]



### nuxt.js
npx create-nuxt-app [project-name]
npm run dev



### nuxt.js scratch
npm install --save nuxt



### nuxt.js firebase
npm install --save firebase@6.2.4
npm install --save vuexfire@3.0.1

### nuxt.js 環境変数設定
npm install --save @nuxtjs/dotenv@1.3.0

### musicLibrary
yarn global add @vue/cli-init
vue init webpack projectName
↓
cd music-library
npm install bulma
npm i --save @fortawesome/fontawesome
npm i --save @fortawesome/vue-fontawesome
npm i --save @fortawesome/fontawesome-free-solid
【Heroku】HerokuでAppを作る

# herokuでアプリをリリースする

### 注意点
1. Herokuの無料アカウントは作成済み。
2. Google Chromeで作業実施。
3. 今回はAppの枠を作ることが目的です。

## 1.ダッシュボードからnew>Create New Appを選択。
- 初めての作成なら、直接、Create New Appでも可。
![NoName_2019-8-10_1-40-25_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/d9e40558-e2e1-13b5-da41-1e5eaa525a74.png)


## 2.App nameを入力し、Create Appを選択。
![NoName_2019-8-10_1-41-10_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/70b1a269-dd43-42a3-b1aa-7a1e72ba64b7.png)


## 3. DashBoardに2.で入力したApp nameのAppが作成できていることを確認する。
![NoName_2019-8-10_1-45-41_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/4a745d0e-9f9e-3429-c49e-cd0c1d59cf3f.png)
(Windows)Vue-CLI3をインストール

#vue-cli3をglobalにインストール

##前提条件
nodejsとnpmがインストールされていること。

(参考)Windows10／node.jsをインストール
https://qiita.com/Dasoi5/items/5e8cb7562c8c72a8e6c0

##vue-cliのインストール
ネットの情報に倣い、`-g`オプションを付けてglobalにインストールする。
※cli3をインストールする場合、`@vue`とする点に注意。
`$ npm install -g @vue/cli
…
+ @vue/cli@3.10.0
added 848 packages from 576 contributors in 57.122s`

##vue/cli-initのインストール
`$ npm install -g @vue/cli-init
…
+ @vue/cli-init@3.10.0
added 256 packages from 208 contributors in 22.96s`

##失敗例
###vue-cli2xがインストールされてしまった
vue-cli3をインストールしたいのに、vue-cli2xがインストールされてしまったので備忘録。
VSCodeのTerminal(bash)で以下のコマンドを実行
`$ npm install -g vue-cli
…
+ vue-cli@2.9.6
added 241 packages from 206 contributors in 18.168s`

npm3系のインストールコマンドは"@Vue/cli"とする必要があるらしい。

###vue-cli2xをglobalからuninstall
`$ npm uninstall -g vue-cli
removed 241 packages in 3.341s`
初心を忘れた人が改めてソースコードについて考えたお話 「名前編」

プログラミング、初級者++向けの記事です。
証拠に基づいた記事ではございませんので、ポエムに近い印象があったらすみません。

名前について
------

名前付け、苦労してますか。
その苦労はとても良い経験であると、個人的に考えます。
プログラミングにおいて、いえ、ビジネスロジックにおいても、名前付けは重要かつ繊細な作業です。一つのクリエイティブな作業でもあるでしょう。

- 一般的な慣習に従うのか
- 新しい名前を生み出すのか

たったそれだけの事で、後々の効果はバタフライの如く変わってしまうものです。

### 名前と意味

名前には、意味があります。
いえ、正確には、**人が名前に意味を付ける**のです。
では、**意味とは一体何なのか**・・？。

ここで重要なのが、**対応(マッピング)**という考え方です。
例えば「猫」という名前には、「生物学における、あらゆる猫科の動物」という意味がありそうです。ただ、シンプルに考えてみると、人が「猫」であろう動物を指差して、「猫、と言った」事が起源ではないでしょうか。
ただし、**文脈**と呼ばれる存在により、**名前の意味が変化**します。

例えば、**猫**という名前と**生物学**を与えて、意味を返す関数を考えます。

```
intention = f('猫', '生物学')
```

次に、**猫**という名前と**猫を指差して「猫」と言った**の意味を返す関数を考えます。

```
intention = f('猫', '猫を指差して「猫」と言った')
```

どちらも、関数fにとっての**文脈**は、与えられた引数だけと決めます(グローバルやスタティックな変数、定数は影響しないとします)。

関数fは、受け取った引数から、出来るだけ意味を推論する仕様としましょう。
こうして、二つの対応を作る事が出来ました。
もし関数fが、自分だったとしたら、どういう意味を返してくれるでしょうか。
引数の意味を知らなければ、曖昧な応えがあるでしょう。「分からない」というエラーが返ってくるかもしれません。

そう、お気付きかもしれませんが、実は**関数fですら、文脈の一つ**になっているのです。



過去、私個人が名前付けの強さを感じたのは、WIN32SDKというWindows用のSDK(software development kit)でした。
このSDKのソースコードはC言語で書かれており、マクロと呼ばれるプリプロセッサを駆使していました。
マクロというのは、シンプルに言えばテンプレートです。単に文字、文字列をコンパイル前に置き換える事がメインです。
そのマクロは、文字を置き換える事がメインであるのに、何と**何も置き換えないでソースコードから消えるだけのマクロ**がSDKのソースコードに書いてあるじゃありませんか。
この時の私は、混乱しました。中級者にすらなれていないと自負があり、ろくな学もない自分には、当然の反応でした。

インターネットも発達していない時代に、少しの情報もググれずに「意味が分からない」という文字列が頭のスタックを埋め尽くし、スタックオーバーフローしたのでした。

しかし、インターネットのおかげか、プログラミングの文化は加速しました。C言語よりも進んだ高級言語が次々と生まれ、**意味の加速**まで行われたように感じました。

しばらくして、JAVAやC#を触るようになり、故郷を思い出すかのように、WIN32SDKを見ました。そうすると、意味不明でしかなかった「あのマクロ」が、腑に落ちたのです。

「ああ、意味を付けていたのか」と。

コンパイル前に消えてしまうだけの邪魔でしかないマクロ、そういう価値観は消えていました。
その「意味」というのは、他ならぬ文脈であり、一意性のためでありました。
例えば`int`という整数の型をわざと名前を変えて`typedef int age;`とするのは、一つの思いやりです。
例え同じ整数の型であっても、`typedef int year`とした場合では、`age`型と`year`型では、意味に違いがあります。
意味に違いがあるという事は、「どこかの文脈では、変数の扱い方を変える必要がある」という事です。

今でこそ、JAVAにおけるアノテーションや、C#における属性についてのメタプログラミングと呼ばれる方法は、一般的に認知されましたが、過去のプログラミング言語においては、メタプログラミングはプログラマーのテクニック、思いやりとして表現されていたのです。
(表現が今は無くなった、と暗に言ってはいません)

### 名前と形式

形式は、コンパイラーが**形式の意味**を解釈してくれます。
しかし、形式と対になっている**名前の意味**は、人が決めて、解釈しなければなりません。

**その名前は、その文脈において、一体何を意味すべきか**

名前付けには、想像以上の価値があります。
自分の名前を思い出して下さい。公的には名前を変えられますが、ほとんどの人は、名前を変えずに数十年という歳月を生きます。プログラムも自分が生きた証のように、残る事があります。
一般的、慣習的な名前が悪いのではありません。
新しく、斬新な名前が良いのではありません。
そこに「自分が考えられる限りの思いやり、意味を込めて付けた名前」が、良いのです。

途中からポエムのような形になってしまい恐縮です、お読み頂きありがとうございました。
AWSを無料でお勉強：課金アラームをセット

最近AWSコンソールを触っていなかったのでお勉強がてらいろいろやってみようと思います。やる前にコンセプトを考えてみます。

###コンセプト
・お金かけてまでやりたくないので基本的に無料でAWSを勉強する
　→ちょっとしたサービスを起動すると結構高額になりやすい。
・高いレベルのセキュリティ確保を目指す
　→アカウントを不正に使われるととんでもない額を請求されるので防ぐ

さて、これまでEC2を起動したりいろいろやってましたが、無料枠期限を超えてからは全部消してしまいました。現状残っているのはMFA済みのrootアカウントと課金アラームのみ。


###課金アラームを確認
いつぞやに設定して以来そのまま放置されているアラーム。ちなみに、一度だけ機能したことがあって、その時は焦りました。AWSの無料枠って基本的なものは１年間有効なので、有効期限到来前に全部インスタンス消していたんですよね。が、なぜか課金されて乗っ取られたか？と思った訳なんです。でも請求は超少額。アカウントに入ってみると昔取得したバックアップがS3に残っていたというありがちなオチでした。。。

なので、機能することはわかったのですが、まあ何を設定したかもまるで覚えていないので確認するところからはじめます。

まず、Cloudwatchって無料でどこまで使えるんよ？の確認から。現状課金アラームを入れていて料金がかかっていないので実績あり！なんですが、ってもよくわからんのでマニュアルで確認です。
https://aws.amazon.com/jp/cloudwatch/pricing/
これを読む限り沢山のメトリクス、アラームを作らなければ大丈夫そうですね。

さて、実際にパラメータを確認します。よくわからんのが統計と期間。ここもマニュアルを見ていきましょう。
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Statistic

####統計とは
>統計は、指定した期間のメトリクスデータの集計です。CloudWatch は、カスタムデータまたはAWS の他のサービスから CloudWatch に提供されたメトリクスデータポイントを基に、統計を提供します。集約は、指定した期間内に、名前空間、メトリクス名、ディメンション、データポイントの測定単位を用いて行われます。
>Maximum　指定された期間に認められた最大値です。この値を用いて、アプリケーションの高ボリュームのアクティビティを判断できます。

とあるので、料金の最大値が取られているはず。オーケーオーケー。

####期間とは
>期間とは、特定の Amazon CloudWatch の統計に関連する時間長です。各統計は、指定された期間に収集されたメトリクスデータの集約を表しています。期間は秒数で定義され、期間の有効な値は、1、5、10、30、または 60 の倍数になります。たとえば、6 分の期間を指定するには、期間の値として 360 を使用します。期間の長さを変えることで、データの集約方法を調整できます。期間は、最短 1 分から最長 1 日 (86,400 秒) までになります。デフォルト値は 60 秒です。

ってことみたいなんですが、画面では違うんですよね。
![201908101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/e40ac399-1b49-bca8-1dda-5ce198e56d11.png)

デフォルト6時間っぽいんですが。。。プルダウンの最小は10秒。んで、アラームのところを読んでみると

>高解像度メトリクスでアラームを設定する場合、10 秒または 30 秒の期間で高解像度アラームを指定するか、60 秒の倍数の期間で通常のアラームを設定できます。高解像度のアラームには高い料金が発生します。高解像度メトリクスの詳細については、「カスタムメトリクスを発行する」を参照してください。

とあるのでこっちっぽいですな。

![201908102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/ce4741eb-e5e3-fb7b-ac3b-f068c608df07.png)

さて、次によくわからないのが、静的と異常検出。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch_Anomaly_Detection.html

を見てみると、なるほどー。今回の場合は静的のほうがいいですね。でもトレンドから異常と判断させることもできるので、そういう時には異常検出なんですね。

![201908103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/6e8d6bab-ed79-4ff9-b914-d9b5c4b7d6e8.png)

次の項目はメールアドレスに飛ばしているのでこのままでOK。

気になる設定はこのくらいです。
よし、このままセットしておくので良さそうです。
また無料枠を超えるようなことがあれば教えてね。よろしく。
Minikube v1.3.0 on Mac 

#はじめに
Kubernetes(aka k8s)を少し勉強しようと思い、MacでMinikubeを使おうと思ったらハマったので解決方法を記録しておきます。

#動作確認環境
OS:macOS Mojave Version 10.14.6 (18G84)

#1. 失敗したケース （xhyveを使用）

``` 
~ tworks55$ brew install kubectl
~ tworks55$ brew cask install minikube
~ tworks55$ brew install docker-machine-driver-xhyve
~ tworks55$ sudo chown root:wheel $(brew --prefix)/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve
~ tworks55$ sudo chmod u+s $(brew --prefix)/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve

~ tworks55$ minikube start --vm-driver=xhyve
😄  minikube v1.3.0 on Darwin 10.14.6
💣  The driver 'xhyve' is not supported on darwin
```
xhyveではダメのようなので別のVMに変更

#2. 成功したケース（hyperkitを使用）

hyperkitを使うとうまく起動しました。

```
~ tworks55$ brew install hyperkit
~ tworks55$ brew install docker-machine-driver-hyperkit
~ tworks55$ ls -l /usr/local/opt/docker-machine-driver-hyperkit/bin/
~ tworks55$ sudo chmod u+s $(brew --prefix)/opt/docker-machine-driver-hyperkit/bin/docker-machine-driver-hyperkit
~ tworks55$ minikube start --vm-driver=hyperkit
😄  minikube v1.3.0 on Darwin 10.14.6
🔥  Creating hyperkit VM (CPUs=2, Memory=2000MB, Disk=20000MB) ...
🐳  Preparing Kubernetes v1.15.2 on Docker 18.09.8 ...
💾  Downloading kubeadm v1.15.2
💾  Downloading kubelet v1.15.2
🚜  Pulling images ...
🚀  Launching Kubernetes ... 
⌛  Waiting for: apiserver proxy etcd scheduler controller dns
🏄  Done! kubectl is now configured to use "minikube"
```

# 参考URL
[https://gist.github.com/inadarei/7c4f4340d65b0cc90d42d6382fb63130](https://gist.github.com/inadarei/7c4f4340d65b0cc90d42d6382fb63130)
jsの論理演算子の順番

```js
const a = 1
const b = 2
console.log((a === a && a === b) || b === b) //--- ①
console.log(a === a && (a === b || b === b)) //--- ②
console.log(a === a && a === b || b === b) //--- ③
```

①、②はtrueってわかるけど
③は、`a === a && a === b`の時点でfalseが返されるもんだと思ってた。
実際はすべてtrue
SESで働くエンジニアのメリットについて考える

##前置き

※この記事はあくまで私一個人の経験や意見ですので、
そうではないと思う方もいると思いますし、その方を否定はしているものではありません。

##なぜこの記事を書いたか

SESをネットで検索すると極端に悪く言った記事とか、ネガティブなワードが結構出てきたり、
違法契約が～云々等の内容が多くて、あまり良い印象を受ける人は少ないと思います。

ただ実際にSESで働いている人は大勢居るわけで…

私自身も3年近くSESで客先駐屯おり、そこでの経験も踏まえて、
少しでもSESで働くエンジニアにとってポジティブな記事を、と思いこの記事を書くことにしました。
契約云々とかの話は他の記事を読んでください。

##エンジニアがSESで客先駐屯するメリットとは？

##人脈が増える

一番はこれかなと思います。
SESを通して色々なプロジェクトで大小様々な企業にお邪魔させて頂くのですが、
そこで同じチームになった人や、その会社の役職者等の沢山の方と知り合うことが出来ます。
どの様な仕事でもそうですが人脈が増えるのは、今後のプログラマ人生において大きなメリットと言えるでしょう。

実際に私は、フリーランスの方と仲良くなって勉強会を開催したり、
ITイベントに呼んで頂いたりということもありました。
某大企業の時はプレミアムフライデーの恩恵も受けられたりしました。
郷に入れば郷に従うのも悪いことばかりではないです。

##技術知識の幅が広がる

当然プロジェクト毎に使用されている技術というのは変わります。
プログラミング言語でいうとAプロジェクトはJavaで、BプロジェクトはPythonだったりする訳ですが、上記の用に色々な人と仲良くなると皆色々と自分の得意分野の技術を教えてくれたりします。

そうなると触っていないところでもある程度知識がついてきたりするので、
私が新人の頃は技術の視野を広げる良いきっかけになりました。

あと実際に声をあげてみると触らせて貰えたりもしました。
※基本的に契約でダメかもしれないので、そこは気をつけてください。

##現場を変えることでマンネリを防げる

飽き性な人だと1年以上も同じ場所で働いていると、
慣れによるマンネリ等でモチベーションがあまり上がらなくなってくることもあるかと思います。

そんなときに働く職場を変えるという選択肢があると、気持ちもリセット出来るので良いと思います。
例え自分と合わない人とでも、契約切れたら会わなくなるからと考えると、意外と付き合えたりするかも知れません。

勤務先が変わると、ランチするところも変化するので、
新たにお店を開拓するのも楽しみの一つですね。

##面談が出来る

案件を頂いた際に、そこの会社のPMやら幹部といった方々と面談するのですが、
この面談で、社内評価では探れない自分の市場価値みたいなものも測れたりします。

定期的に社外の人からフラットな評価を貰える環境は、個人的にありがたいです。

例え社内でどんなに評価が高く、自分にどんなに自信があったとしても、
マーケットのニーズに合わなければ、市場価値の高いエンジニアとは言えないと私は思います。

##最後に

色々と書いてみましたが、
良いこともあれば当然悪いこともあるわけで、その辺の話については、
他の方がまとめてくださっているのでそちらを見ていただければと。

ただ今こうして自分がプログラマとして働けているのも、
SESを通して出会った素晴らしい先輩エンジニア達に育ててもらったからなので、
あんまり悪いことばかりでもないよ～というポジティブな意見も言わせて頂きました。
pythonのビット単位演算


```python:python
# AND
>>> bin(0&0)
'0b0'
>>> bin(0&1)
'0b0'
>>> bin(1&0)
'0b0'
>>> bin(1&1)
'0b1'

# OR
>>> bin(0|0)
'0b0'
>>> bin(0|1)
'0b1'
>>> bin(1|0)
'0b1'
>>> bin(1|1)
'0b1'

# XOR
>>> bin(0^0)
'0b0'
>>> bin(0^1)
'0b1'
>>> bin(1^0)
'0b1'
>>> bin(1^1)
'0b0'
```
pythonのシフト演算


```python:python
# 左シフト
>>> bin(3)
'0b11'
>>> bin(3<<3)
'0b11000'
>>> 3<<3
24
>>> 3*pow(2,3)
24
```

```python:python
# 右シフト
>>> bin(3)
'0b11'
>>> bin(3>>3)
'0b0'
>>> 3>>3
0
>>> 3/pow(2,3)
0.375
```
Windows10／node.jsをインストール

#nodejsのインストール
Windowsにnode.jsをインストールするには、node.js公式からインストーラーをダウンロードして実行する。

nodejs公式
https://nodejs.org/ja/download/

設定はデフォルトでOK

#nodejsのインストール確認
コマンドプロンプトやpowershell、任意のターミナルからバージョン確認

`$ node -v
v10.16.2`

`$ npm -v
6.9.0`

※筆者はVSCodeのbashから実行したが、VSCodeを再起動しないとバージョン確認ができなかった。
HTMLとCSSを使う際の注意点ーProgateのHTML＆CSS学習コース中級編を終えてー

# はじめに

未来電子テクノロジー（https://www.miraidenshi-tech.jp/intern-content/program/）
でインターンをしている@imurutaです。
プログラミングを始めて間もないですが、学んだことをまとめてみようと思います。
＊プログラミング初心者であるため、内容に誤りがあるかもしれません。もし、誤りがあれば修正するのでどんどん指摘してください。


#HTMLとCSSを使う際の注意点

今回はHTMLとCSSについて学んでいく中で「ちょっと複雑だな」あるいは「これは少し工夫がいるな」と感じた部分について、問題点とその解決策をご紹介します。


# 背景画像は表示範囲を埋め尽くすまで繰り返してしまう

・問題点
background-imageで指定された背景画像は表示範囲を埋め尽くすまで繰り返します。1枚の画像だけを表示したいのに、空いたスペースに背景画像の全体または一部が追加で入ってくるイメージです。

・解決策
background-size:cover;を指定すると、1枚の画像で表示範囲を埋め尽くすように画像の大きさが調整されます。これを使えば、いちいち画像の大きさを指定する必要はありません。


# インライン要素はwidth・heightや上下のmarginを指定できない

・問題点
インライン要素はwidth/heightや上下のmarginを指定することができません。

・解決策
この問題はインラインブロック要素に変換することで解決できます。インラインブロック要素はインライン要素と同じように横に並びますが、幅や高さを調整できます。具体的には、displayプロパティを使うと要素の変換ができます。
例）ボタンをインラインブロック要素に変換する場合
    .btn {
    display: inline-block;
　　}


# positionを使うと要素の重なりが生じてしまう

・問題点
position:fixed;を使うと要素を特定の位置に固定できます。しかし、他の部分を動かすと要素の重なりが生じてしまいます。結果、見せたい要素が隠れてしまうことがあります。

・解決策
z-indexプロパティを用いれば要素の重なりの順序を指定できます。z-indexは整数値で指定し、値が大きいほど上に表示されます。


# おわりに

今回はHTMLとCSSを使う際の注意点についてご紹介しました。今回取り上げたもの以外にも注意点はまだまだあります。これからプログラミングを学んでいくと複雑で難しい内容がさらに増えていくと思います。そのため、複雑だなと感じた点を1つずつ着実に頭に入れていこうと思います。
HTMLとCSSを使えば何ができるのか？ーProgateのHTML＆CSS学習コース初級編を終えてー

#はじめに
未来電子テクノロジー（https://www.miraidenshi-tech.jp/intern-content/program/）
でインターンをしている@imurutaです。
プログラミングを始めて間もないですが、学んだことをまとめてみようと思います。
＊プログラミング初心者であるため、内容に誤りがあるかもしれません。もし、誤りがあれば修正するのでどんどん指摘してください。


# なぜHTMLとCSSを学ぶのか

プログラミングが利用されている基本的なものの1つにWebページがあります。
このWebページを作成する際に使われるプログラミングの言語がHTMLとCSSです。
そのため、HTMLとCSSを学べばWebページを作れるようになります。
つまり、Webページを自力で作れるようになることが最終的なゴールとしてあります（もしかしたら他にもできることがあるかもしれませんが、とりあえずの目標としてWebページを作れるようになることを挙げておきます。）。
HTMLとCSSのそれぞれにおいて具体的に何ができるのかについては以下で説明します。


# HTMLでできること

まずは、HTMLを使ってできることについてざっくりと説明します。
HTMLを使えば、ページ上に文字や画像を表示させられます。
また、リンクや文章入力欄を作成することもできます。
こうした文字や画像などは一定の色や大きさで上から順に羅列されます。


# CSSでできること

次に、CSSを使ってできることについて同様にざっくりと説明します。
HTMLだけでは各要素（文字や画像など）の色や大きさなどを調整できません。
また、それらの配置も変えられません。
そこで役立つのがCSSです。
CSSを使えば、HTMLの各要素の色や大きさ、配置などを変更できます。
背景の色を変更することもできます。


# まとめ

ここまで、HTMLとCSSを使ってできることについてご紹介しました。
ページ内の主なコンテンツを作成するのがHTML、色や大きさ、配置などを調整してページをデザインするのがCSSです。
個人的には、メインがHTMLで、そのサポート役がCSSであるというイメージを持ちました。


#おわりに

ProgateのHTML＆CSS学習コース初級編を終えて、手を動かしながらWebページの作り方を学ぶことができました。
しかし、まだまだ自分で何かを作れる段階にはありません。
これから中級編にも挑戦し、プログラミングスキルを高めていきたいと思います。
.gitignoreの役割

#.gitignoreとは?

全ディレクトリの下の方にあるgitのロゴがついたディレクトリのこと。
https://gyazo.com/fd1c830568e1d690557ecdc6c60b8778

これは、GitHub上のリモートリポジトリにプッシュしたくないファイルがある場合、このファイル内のそのプッシュしたくないファイルとディレクトリの構想を記述すると、リモートリポジトリにプッシュした時にGitHub上に反映されなくなるという仕組みを持っている。

```.gitignore
/config/credentials.yml.enc
```

#リモートリポジトリにプッシュしたくないファイルとは?

aws_secret_access_keyやcredential.yml.encのmaster_keyなどがこれに当たる。その理由は、これらをインターネット上に公開してしまうと、第三者にAWSのリソースを悪用されてしまい、高額請求の被害に遭ってしまう恐れがあるためである。
モジュールもオブジェクト、import文で変数に代入

Pythonではモジュールもオブジェクトです。
Pythonインタープリタが`import`文を見つけると、指定されたファイルをコンパイルして`module`オブジェクトを作り、変数に代入します。
関数の中に`import`文を書くと、関数を呼ぶ度に`import`処理してしまいます。モジュールはキャッシュされるので、2回目からはキャッシュされたモジュールが変数に代入されます。PEP8では`import`文をファイルの先頭にまとめて書くことを推奨しています。

以下の`import`文は、

```py
import math
import numpy as np
from random import choice
from random import randint as ri
```

Pythonインタープリタは以下のように解釈して実行します。
[`__import__`は組込み関数](https://docs.python.org/ja/3/library/functions.html#__import__) です。
**※注意※：** リンク先に書いてありますが、ユーザプログラムでは`importlib.import_module()`を使いましょう。

```py
math = __import__('math')
np = __import__('numpy')
choice = __import__('random').choice
ri = __import__('random').randint
```

`vars()` で変数辞書を確認してみます。

```py:実験
>>> import math
>>> vars()
{（中略）,
 'math': <module 'math' from '/usr/lib/python3.6/lib-dynload/math.cpython-36m-x86_64-cygwin.dll'>}
>>> random = __import__('random')
>>> vars()
{（中略）,
 'math': <module 'math' from '/usr/lib/python3.6/lib-dynload/math.cpython-36m-x86_64-cygwin.dll'>,
 'random': <module 'random' from '/usr/lib/python3.6/random.py'>}
>>> random.randint(1, 100)
11
>>> from random import randint as ri
>>> vars()
{（中略）,
 'math': <module 'math' from '/usr/lib/python3.6/lib-dynload/math.cpython-36m-x86_64-cygwin.dll'>,
 'random': <module 'random' from '/usr/lib/python3.6/random.py'>,
 'ri': <bound method Random.randint of <random.Random object at 0x60029f1e8>>}
>>> ri(1, 100)
15
```

`import`文は、指定したスクリプトファイルを読み込んで`module`オブジェクトを作成して変数に代入する処理の**シンタックスシュガー（糖衣構文）**と言えます。
Terraformのメモ（awsのリソース設定でうっかりしてたあたり）[WIP]

# これはなに？

Terraformを使ってリソースをimportしてから、リソースを削除し、再びplan / applyで同じように作れるかのテストの際に、気がついたあたりを書き出します。
完全に個人メモ用です。
（WIPで随時更新）

# 補足情報

```
# 20190810時点
$ terraform -v
Terraform v0.12.6
+ provider.aws v2.23.0
```

# planで通ってもapplyの段階でNGになるもの

## S3

### bucket name

- bucket nameのユニークさ
 - URLとしてユニークになる必要がある
 - Ref. <https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/BucketRestrictions.html>
 - バケット作成の設定を書いてterraform planしたところでは、バケット名のユニークさまではチェックされなかった
 - applyしたら「その名前は使われてます！」と怒られてエラーに

#### 注意点

- TerraformのtfstateをS3上で管理するため、バケットを以下のように指定
- ありがちな ``my-terraform-state-storage`` といった名前にすると、planした際にバケット名（アクセスできるエンドポイント）がユニークにならないとエラーが発生してしまう
- 仮装ホスト形式
  - http://{自分のバケット名}.s3.amazonaws.com/ になる
  - 考えてみると、バケット名をexample...とかtest...とした場合、重複する可能性は高い
- リージョン指定で作成しリージョンごとのエンドポイントの形式でもアクセスできるけれど、やっぱり http://{自分のバケット名}.s3.amazonaws.com/ としてのユニークさが必要

#### 設定例

```hcl

terraform {
  required_version = ">= 0.11.7"

  # backendでは変数を利用できないので、先にバケットとテーブルを作成しておき固定値を入れる
  backend "s3” {
    # bucketに注意！！
    bucket         = "my-terraform-state-storage"
    key            = "terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "terraform-state-lock"
  }
}
```

※サンプルのソースコードなどの設定をそのまま使ってしまったりすると、詰むことがあります...。

## ALB (Application Load Balancer)

### subnet

- ALBを作成する際には、異なるアベイラビリティゾーンに所属する2つ以上のサブネットを指定しないといけない
 - Ref. <https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/create-application-load-balancer.html>
 - ``VPC から少なくとも 2 つのアベイラビリティーゾーンを選択します。``のあたり。
 - planの段階では subnets = [] （ブランク）でもOKが出てしまう

#### 設定例

- Jenkinsを立てるのでその前にALBを配置したいという例で
 - ターゲットグループやリスナーは別に設定なので、``resource: aws_alb`` のみ抜粋

```hcl

resource "aws_alb" "jenkins-alb" {
  name               = "jenkins-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = ["${aws_security_group.allow-tls.id}", "${aws_security_group.allow-http.id}”]

  # subnets指定なので2つ以上必要
  # subnets = [ ] でブランクでは作成できない
  subnets = [
    "${aws_subnet.terraform-sample-subnet-1d.id}",
    "${aws_subnet.terraform-sample-subnet-1c.id}"
  ]

  enable_deletion_protection = false

  access_logs {
    bucket = "${aws_s3_bucket.jenkins-alb_logs.bucket}"
    enabled = true
  }

  tags = {
    Environment = "production"
  }
}
```

## そもそも権限が足りない

rootアカウントや、rootアカウントの代替用として作った強いアカウントではなく、ある程度の権限を与えたアカウントで作業する方針にしている場合、**planの際にどうしても権限エラーで失敗してしまう**ことがあります。

## 感想など（時々追加するかも）

自動でも手動（コンソール）でもどちらも同じですが、明確に1リソースに対しての処理を行うのではなく、複数の依存するリソースを更新・削除といったことをする場合、1箇所でエラーが発生すると、「**何が残っていて何が消えたのか**」がわかりにくくなります。
(これはAWSに限らず）

最初のうちや、無料枠で試している際は、便利なウィザードを使って一式試している場合などに、消し忘れで課金が発生...ということもあるかもしれません。

なるべく綺麗な環境で作る -> 壊すことで確認が大事とは実感しています。

そういう意味で、自動で構成する場合はタグ付けといった措置で、ある程度把握できるのかなとは思いますが、なかなかそこまでわたしは頭が回りません。
Pythonでのモジュールのインポート

importはsys.modules（モジュールキャッシュ、すでに読み込まれているモジュールとモジュール名がマップされた辞書）から検索を始める。以下でキャッシュの内容を確認できる。

```python:python
>>> import sys
>>> sys.modules
{'builtins'': <module 'builtins' (built-in)>, 'sys': <module 'sys' (built-in)>, '_frozen_importlib': <module 'importlib._bootstrap' (frozen)>, '_imp': <module '_imp' (built-in)>, '_warnings': <module '_warnings' (built-in)>, ...'>}
>>> sys
<module 'sys' (built-in)>
```

```python:python
# （>>> import pandasをして確認すると．．．、大量なのでここには載せない）
>>> pandas
<module 'pandas' from '...anaconda3-5.2.0/lib/python3.6/site-packages/pandas/__init__.py'>
```
vuetifyのv-textareaの高さを変更する

#はじめに
普段はiOSエンジニアをしています。
仕事でvue.js+vuetifyでSPAでお問い合わせ画面を作る機会があったので、その備忘録です。

##環境
vue 2.6.10
vue-cli-plugin-vuetify 0.6.1
vue-router 3.0.7
vuetify 2.0.4
vuetify-loader 1.3.0

#textareaの設置方法

``` html
<v-textarea></v-textarea>
```

設置にはv-textareaを使います。

#その他オプションを追加していく
```html
<v-textarea outlined
 name="input-7-4" v-model="message" :rules="messageRules" required label="Message"></v-textarea>
```
<img width="683" alt="スクリーンショット 2019-08-10 7.02.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184792/a132c201-8517-497f-b183-68abb6d5d3f1.png">

こんな感じになります。

#高さを変更する

高さの変更はrowsを追加します。

``` html
rows="20"
```

なのでこんな感じ

```html
<v-textarea outlined rows="20" name="input-7-4" v-model="message" :rules="messageRules" required label="Message"></v-textarea>
```

<img width="648" alt="スクリーンショット 2019-08-10 7.09.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184792/1fa9e165-4384-51fb-8ace-1ed17789f865.png">
はいできました。

簡単ですね。

#終わり
vutifyはドキュメントが充実しているので、まずはドキュメントを見るのが一番いいかと思います。
[vuetify公式ドキュメント -textarea-]
(https://vuetifyjs.com/ja/components/textarea#api)
C++のstringオブジェクトはありがたいという話

#事の起こり
先日、同僚からC++のstringオブジェクトっているの?という質問を受けました。そこで、今回は私の考えるstringオブジェクトのありがたみについて書いて見ようと思います。

#stringを用いたありがたいコード
C++のstringオブジェクトを使うと下記のようなありがたいコードが書けるのです。なんと、**文字列の代入ができるのです!!** ・・・
**これだけ!? 何がありがたいの?** と思われる方もいると思うので、経緯を説明していきますね。

```cpp:cpp
string str;
str = "aaaaa"; //代入できる!!!
```

#c言語の文字列は代入ができないという話
**下記コードのように描けば、文字列の代入くらいC言語でもできるでしょ** と思われる方もいらっしゃるかもしれませんが、残念ながらできません。それは、なぜか

```c:c
char str[5];
str = "aaaa";//Array type 'char [5]' is not assignable
```
少し考えれば分かりますが、上記のコードのstrは文字列strの先頭アドレスを示しています。したがって、str = "aaaa"というのは、**アドレス = 文字列**となってしまっていてC言語の構文的におかしく、代入はできません。
**じゃあ、どうするのか・・・ strcpyの出番です!!**


#もはや脆弱性の代名詞になってしまったstrcpy君
C言語では、文字列の代入を行う時はstringライブラリのstrcpy関数を使用します。

```c:c
char str[5];
strcpy(str,"aaaa");
printf("%s",str);//aaaaと表示される
```

**以外と簡単じゃないか、stringなんて必要ないな**と思っていた時期が私にもありました。実はc言語のstrcpyは非常に危険なんです。例えば、上のコードを少し書き換えて、文字列の要素数を5から3に変更します。

```c:c
char str[3]; //配列の要素数を変更
strcpy(str,"aaaa");
printf("%s",str);//aaaaと表示される
```

こうすると**なんと!!!・・・ エラーが起きないんですね。(環境によっては警告が出ます。)**でも実際は、文字列strのサイズ(この例では3)を超えた領域に書き込みを行うバッファオーバーランが発生しているのです。**サイズを超えた領域はどこか?? なんてことは誰にも分かりません。**奇跡的に問題ないかもしれませんが、書き換えてはいけない領域を書き換えてしまうこともあります。(制御系のソフトウェアだと一発アウトですね)
このように、strcpyは大変危険な脆弱性を孕んだ関数なわけです。**実際、情報セキュリティ系の資格試験でもstrcpyの脆弱性について出題されたことがあるくらいです。**この危険を避けるために、strncpyやstrlcpyなどがあります。しかし、どちらもバッファオーバーラン以外の問題を抱えており、C言語における文字列への代入の面倒を解消するに至っていません。
こんな感じで、**C言語では文字列への代入を行うだけでも命がけなわけですね。こう考えると、代入が楽々行えるstringオブジェクトはとても魅力的です。**




#まとめ
C言語の不便さが解れば、C++のありがたみも分かるというお話でした。もちろん、C言語の文字列もあらかじめ適切な長さが分かっていれば、メモリを無駄遣いせずにすむという利点もあります。また、文字列と言う名の配列なので一文字ずつのアクセスは別格に速いです。というか、C++のstringオブジェクトってC言語の文字列をメンバに持っていて、いろんな便利機能をメンバ関数とかoperatorとかを使って拡張したものなんですよね。だから、**本質的にあまり違いはないんですよ**。使い分けるとしたら、その文字列に行う操作が明確な場合はC言語の文字列を、文字列に行う操作が明確でない場合はstringオブジェクトをといった感じだと思います。私は単純にC言語のstring.hの関数は使うのが怖いので、stringオブジェクト派ですね。


#追記(2019/8/10)
文字列の代入だったら、文字型のポインタを使えばいいと言うご指摘を受けました。

```c:c
const char* str;
str = "aaaa";
printf("%s",str);
```

こうすれば、代入も難なく行えます。また、バッファオーバーランの問題もありません。
ただ、この書き方だと、文字列リテラルが配置される領域は静的領域に確保されるので一文字だけの変更をしようとしても、メモリアクセスエラーとなってしまうなどの欠点もありますね。(**文字の変更をしようと思ったら、文字型配列を使わないといけないジレンマが・・・**)

```c:c
char *str; //constがないことに注意、警告が出ます
str = "aaaaa";
str[3] = 'b';//Thread 1: EXC_BAD_ACCESS
printf("%s",str);
```

まあ、色々書きましたけど、C言語の文字列は難しいんですね(静的領域に確保されるかスタック領域に確保されるかとか)。その点、C++のstirngオブジェクトはもちろん問題点もありますけど、使いやすくて便利なんですよね。利点はこれに尽きるかもしれません。メモリと速度の観点でいったらC言語の文字列を、柔軟に文字列の操作を行いたい時はstringオブジェクトをといった使いわけかな・・・
[MySQL]簡単にサンプルデータを入手。imprtする方法

##1.サンプルデータを取ってくる
[テストデータ生成](http://tm-webtools.com/Tools/TestData)
説明に従って必要な分だけサンプルデータを作成**CSV**でダウンロード

##2.サンプルデータをimport
ダウンロードした**CSV**データをSQLクライアントを使ってfileからimport
次いでtableとcolumnを指定してimport

##後書き
お気づき、ご指摘がありましたら
とても助かります。
よろしくお願いします。
gulp v3からv4への記述法移行

gulp.jsがv4になり、`gulp.task`が非推奨になったとのことで、それを使用しない記述方法をメモも兼ねて記事として残します。

## 自動化処理について
gulpfile.jsでは以下を自動化しています。

- ローカルサーバ起動
- ファイル変更監視してのブラウザ自動リロード
- Sassファイル -> CSSファイルへの自動コンパイル

## v3までの記述方法
```
const gulp = require('gulp')
const sass = require('gulp-sass')
const browserSync = require('browser-sync')

// ローカルサーバ起動
gulp.task('build-server', function(done) {
  browserSync.init({
    server: {
      baseDir: './'
    }
  })
  done()
})

// ブラウザ自動リロード
gulp.task('browser-reload', function(done) {
  browserSync.reload()
  done()
})

// Sassファイルのコンパイル
gulp.task('sass-compile', function(done) {
  gulp
    .src('sass/*.scss')
    .pipe(
      sass({
        outputStyle: 'expanded'
      })
    )
    .pipe(gulp.dest('css'))
  done()
})

// ファイル監視
gulp.task('watch-files', function() {
  gulp.watch('./*.html', gulp.task('browser-reload'))
  gulp.watch('./sass/*.scss', gulp.series('sass-compile', 'browser-reload'))
})

// タスク実行
gulp.task('default', gulp.series('build-server', 'watch-files'))
```

## v4での記述方法
```
const { src, dest, watch, series, parallel } = require('gulp')
const sass = require('gulp-sass')
const browserSync = require('browser-sync')

// ローカルサーバ起動
const buildServer = done => {
  browserSync.init({
    server: {
      baseDir: './'
    }
  })
  done()
}

// ブラウザ自動リロード
const browserReload = done => {
  browserSync.reload()
  done()
}

// Sassファイルのコンパイル
const sassCompile = done => {
  src('sass/*.scss')
    .pipe(
      sass({
        outputStyle: 'expanded'
      })
    )
    .pipe(dest('css'))
  done()
}

// ファイル監視
const watchFiles = () => {
  watch('./*.html', browserReload)
  watch('./sass/*.scss', series(sassCompile, browserReload))
}

// タスク実行
exports.default = series(buildServer, watchFiles)
```

## まとめ
`gulp.task...gulp.task...`が無くなっただけでもだいぶコードの見通しがよくなった気がします。
非推奨ということは将来的に廃止される可能性も考えられるので、はやめにv4流の記述方法に慣れるようにしましょう。

## 参考リンク
- https://jackswim3411.hatenablog.com/entry/2019/05/31/034309
PHP 初心者　if構文全般

ここ最近if文を書いてなかったので取り敢えず簡単に書いてみた。あくまでも復習なので変数の値は適当に、三項演算子まで書く時間がなかったので今度書くつもり

```
<p>比較演算子</p>

<?php
$a = 25;
$b = 10;
$c = 20;

if($a ==$b){
  echo 'aとbは同一です';
}elseif($b < $c){
  echo 'bはcより小さい';
}
 ?>

<p>論理演算子</p>

<?php
$x =100;

if($x > 50 && $x < 130){
 echo'$xは50より大きいかつ130より小さい';
}

 ?>


 <P>論理演算子その２</P>

<?php
$old =25;
$hobby ='game';

if($old >= 24 && $hobby >='game'){
  echo '24歳でゲームが趣味です';
}
 ?>

<p>論理演算子その３</p>

<?php
$kamimaho = 100;
$isutoria =  80;

if($kamimaho > 90 or $isutoria >80){
  echo "uguisuは最高です";
}
 ?>

<p>真偽値</p>

<?php
$x = 6;
if($x ==true){
  echo "great";
}
 ?>


結果表示
<p>比較演算子</p>

bはcより小さい
<p>論理演算子</p>

$xは50より大きいかつ130より小さい

 <P>論理演算子その２</P>

24歳でゲームが趣味です
<p>論理演算子その３</p>

uguisuは最高です
<p>真偽値</p>

great
What is the best OS for servers?

<h1>What is the best OS for servers?</h1>
In 2019 there are plenty of server operating systems available for making our works easier and smoother. Each operating systems performs well for different needs.

<h2>Windows server</h2>

We're going to discuss Linux in this article, but still, Microsoft plays a better role for business servers. When compared to Linux Microsoft is not more powerful but when compared to the support of both operating systems Microsoft is always providing a better solution. But still, Microsoft server licence price is too high when compared to Linux. If you are going to do any enterprise web designing related or any Database related solution it's the best choice ever.

<h2>Ubuntu Server</h2>

Ubuntu also user-friendly likes ubuntu-desktop and it's also working with various hardware systems without any hassles. Most of the Ubuntu systems works cloud-friendly that means you can run ubuntu on any cloud environment like AWS, Digita Ocean, GCP and more. And ubuntu also provides premium support at an affordable price, Ubuntu allows Apache and Nginx servers to run without any hassles. It's developer-friendly for <a href="https://lastcyber.com/web-design-company-in-trichy/">web designing</a>.

<h2>CentOS Server</h2>

Cent OS also working like Red hat, it's installing software like a fedora.  This operating system has its own community, A worldwide of community members helps 24*7. This makes CentOS is the best one.

<h2>Red Hat Enterprise Linux Server</h2>

Red Hat Linux is the American based company, It also provides great paid support. It works in the cloud without any hassles.

As a <a href="https://lastcyber.com/web-design-company-in-trichy">Web Design Company in Trichy</a> in trichy we use different types of operating systems for various needs.
WinActor Ver6

WinActor Ver6がリリースされましたね。
Ver6.0.0には問題があったようで、あっさりと公開中止、Ver6.0.1がリリースされました。

さて、技術的なことはさておき、Ver6になっていくつかの便利機能が増えましたね。

個人的にはログダイアログ中のログから対象ノードへのリンクが便利です。
（どうせならログファイルもHTML化して同じようにして欲しいところでしたが）

他にもVBAのようなステップ実行も開発・デバッグ効率が上がりますね。

逆に期待外れだったのが、付箋機能色が変更できず、あまり期待できない機能でした。