OmniAICreator/Qiita-1.07M huggingface dataset:
irbで日本語入力できない、rbenvでRubyのバージョンが指定できない

**プロを目指す人のためのRuby入門(1章-6)**を進める際に、躓いたところを記載しています。

##問題
・irbで日本語入力できない(文字化けされる)

・rbenvでRubyのバージョンの切り替えができない

##やったこと
######・irbで日本語入力できない(文字化けされる)
readlineがインストールされていないため、一度アンインストールし、

```
$ rbenv uninstall 2.6.5
$ brew install readline
Warning: readline 8.0.1 is already installed and up-to-date
To reinstall 8.0.1, run `brew reinstall readline`

$ brew reinstall readline  #長いメッセいーじの後に🍺このマークが表れれば成功だと思います
$ brew link readline --force
$ RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)"
```


######・rbenvでRubyのバージョンの切り替えができない
```
$ rbenv install 2.6.5 　を実行後、
```
```
$ rbenv global 2.6.5
$ rbenv versions  このコマンドではversion2.6.5が設定されているようだが、
  system
* 2.6.5
$ ruby -v
ruby 2.6.0p0 　こちらでは反映されていなかった。
```

いろんな方のサイトを見ても解決できなかったですが、こちらの記事の「rbenvで2.6.1に切り替える」の「バージョン切り替え後半」をそのまま行うと解決しました。
(https://qiita.com/SAYJOY/items/be06302ae8a2fac7f0c4)

その後、irbを起動しようとすると以下のエラーが発生し、起動できませんでした。

```
$ irb  
can't find gem irb (>= 0.a) with executable irb (Gem::GemNotFoundException) と言うエラーが出る
```
gem 側でもirbをインストールする必要があるそうです

```
$ gem install irb
```


これで無事、ターミナルでRubyの操作ができそうです。
中小企業が機械学習を導入する、その前に

### はじめに
最近、機械学習の勉強をしたので、思ったことをまとめてみます。
主観的な部分が多々ありますが、特に中小企業に対する導入への意見が主です。

### 1. 機械学習の導入
クライアントから**機械学習やAIを使ったシステムの導入を提案してほしい**などの依頼があることがあります。

大抵の中小SIerは、機械学習などの経験はなく、途方に暮れることも多いでしょう。
機械学習を導入するためには何が必要なのか、どういった覚悟が必要なのか、そういった観点でまとめました。

### 2. データが大量に必要
機械学習には大量のデータが必要です。
データも何も揃ってないのに、役員の鶴の一声でよくわからない機械学習がスタートすることがありますが、
そのほとんどが失敗していると思います。

##### :file_folder: データを集める
まず、データを集める必要がありますが、一朝一夕にデータは集まりません。
また、データの取り方も重要です。コピーしたような同じデータをたくさん集めても意味がありません。
なるべく同一の者の多くのパターンを集めることが重要です。

数年かけてデータを集めるか、または社内から使えそうなデータをかき集める必要があるでしょう。

##### :wrench: データを保守する
収集したデータは定期的に確認する必要があります。
常にデータを確認し、そこから新しい価値を見つけ出していかなければなりません。

データの収集や保守に力を入れることが出来ない企業は、機械学習の導入を見直すべきです。

### 3. 人員リソースは常に確保
機械学習は、あくまで「学習」です。
世に出したら「はい、おわり」ではありません。常に成長させていかなければなりません。

##### :runner: 何度もトレーニング

機械学習は100％の答えは出せません。
間違った答えを修正してかなくてはいけません。これには人の手が必要です。
勝手に成長していくわけではありません。初期段階では特に、必ず人の手で成長させていくことが重要です。

機械学習は何度もトレーニングして、最適化を図っていきます。

### 最後に
次のページがとてもよくまとめてあります。（人任せ）

**機械学習のデータセットの重要性**
https://qiita.com/nonbiri15/items/b29fe079d359d531bf85

機械学習を導入していくプロセスはおもしろいと思います。
ただ、機械学習を導入することが目的にするのではなく、今の業務を改善することを考えましょう。
今の課題は何なのか、改善するには何が必要なのか、
きっと機械学習じゃなくても解決するものが多いと思います。

それでも機械学習を進めたいなら、予め学習されたAPIを使用しましょう。
Googleでもたくさん用意されています。
小さな市場にマッチするものは少ないかもしれませんが、探すと使えそうなAPIも出てきます。
ただやはり、結構な費用がかかります。。

中小企業では、GoogleのAPIを使用することで実現の可能性が見えても、
費用がネックになって導入を見送ったり、費用対効果が薄い面からも、まだ導入は難しいと考えます。
【GitBucket】push時に「remote unpack failed: error Missing delta base XXXXX」のエラーが出た時の解決法

# 現象

GitBucketで運用しているGitサーバへ数百MB～GB程度の大きめのデータをpushした時に、
「remote unpack failed: error Missing delta base XXXXX」のエラーメッセージが出る。

# 原因

GitBucketを動かしているJavaのヒープメモリ不足。

# 対策

javaの起動オプションにある最大メモリサイズを今より大きな値に設定する。
(指定なし→-Xmx1024M)

# 参考にしたサイト

WindowsでデフォルトのJavaヒープサイズを識別する方法
<https://codeday.me/jp/qa/20190322/434668.html>
windowsでneovim設定

windowsでneovim環境をセットアップするメモ

# インストール

インストールは公式の手順に従ってscoopを使う

* https://qiita.com/honeytrap15/items/256d98f7c4ff96f6502f#neovim

# 設定

必要な言語のランタイムをインストール
neovimを開いて `:CheckHealth` を実行すると足りないものがわかる

## python

2系と3系を入れる
はやく2系なくなってほしい

* https://www.python.org/

ダウンロードからpython2.Xとpython3.Xのインストーラをとってきてインストール
（scoopでも大丈夫かもしれない）

python2系はインストール時にパスを通してくれないので自分で通す
アプリケーションメニューに "Path" とかいれると環境変数の設定が出てくる

pip2とpip3でそれぞれneovimモジュールをインストールしておく

```
> pip2 install neovim
> pip3 install neovim
```

このときビルドエラーが出る場合はc++のビルド環境が足りてないので、visual studioのビルドツールを入れておく

* https://visualstudio.microsoft.com/ja/downloads/

下のほうにある "すべてを展開" をクリックして Build toolsみたいなやつを検索する

## nodejs

ここからはオプショナルだけど入れておけると安心
公式からインストーラをとってくる
（これもscoopでいれたらいいかも）

* https://nodejs.org/ja/

```
> node --version
```

って実行出来たらおっけー
npmにもパスが通るのでneovimモジュールをグローバルインストールしておく

```
> npm install -g neovim
```

## ruby

rubyは公式のインストーラがよくわかんなかったのでscoopでいれた
（ここでscoop使えばよかったのかと気づく）


```
> scoop install ruby
```

gemも入るのでneovimのgemをインストールしておく

```
> gem install neovim
```

# init.vim

init.vimのパスがよくわかんなかったけどこれも `:CheckHealth` に書いてあったので言われた通りのところにディレクトリを作って `init.vim` っていうファイルを作成しておく

```
> mkdir ~/AppData\Local\nvim
```

neovimをひらいて

`:e ~/AppData\Local\nvim\init.vim`

適当に

```
set number
```

とか書いておく

一回終了してもう一回開いたときに行番号が出ればオッケー
AWS初心者が構築してみた-構成図作成

## AWSを勉強し始めた理由
ここ最近AWSをよく触るようになったのと、誰も周りに詳しい人がいないため

# 目的
自分で考え、手を動かし、AWSへの知識を深めること。

# やること
AWS初心者でもできる簡単な構成を考え、作成していく。
構成を考える＆構成図作成

## 前提条件
・AWSアカウント(無料枠含む)が作成済みとなっていること

# ①構成を考える＆構成図作成
## 構成を考える
まず、構成については以下とする。
もう少しだけ凝った構成にしようかと思ったが、それはまた別にやろう。となったので簡単にした。
・東京リージョンに作成
・AZ-aのみ使用
・VPC内にパブリックサブネット/プライベートサブネットを作成
・VPCは10.0.0.0/16、パブリックは10.0.1.0/24、プライベートは10.0.2.0/24とする。
・パブリックにWEBサーバ、プライべートにDBサーバ(EC2)を作成
・DBサーバに接続できるのはWEBサーバのみ
・冗長構成とはしない

## 構成図作成
自分で考えた構成を構成図として表す。
構成図かけるようになったら楽しいよね！っていうことで、どこで作れるのか色々調べたところ、
[**Draw.io**](https://www.draw.io/?splash=0&libs=aws3)というサイトがよさそうだったのでこのサイトを使います。無料なので。
※上記URLからだと設定しなくてもAWSの図形を使用することができます。
※Draw.ioは物凄く便利なので覚えておいても損はないと思います。

簡単にですが使い方を記載します。
・初めに保存先を聞かれるので任意の場所へ。
・保存名聞かれるので適当に。
・図形は左ペインより選択する。GroupsとComputeは良く使う。
・図形の追加は左ペイン下にある[+More Shapes...]を選択すると
・jpeg等でエクスポートしたい場合は[File]->[Export as]を選択。
　※基本的に保存は.drawio形式でして、またいつでも編集できるようにしておく。
![WS000016.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510919/4b8d4dd2-8d4c-3c8b-dc4c-d2db20857184.jpeg)

Draw.ioを使い今回構築していく構成は簡単に以下となる。
![Qiita-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510919/309b45b4-ec6e-34fe-fd35-89b802b43487.jpeg)
【忙しい人向け】基本情報技術者試験概要

# 前提条件
[【忙しい人向け】基本情報技術者試験の必要性](https://qiita.com/keit0728/items/ca58f2a20f4ede0ad6c7)を読んで受ける気になった人向け

# 試験概要
- 試験は年2回、春と秋
- 試験は午前、午後の2部構成
- 午前、午後、どちらのテストでも6割以上点数を取ると合格
- マークテスト方式
- 時間は午前9:30～12:00(150分)、午後13:00～15:30(150分)
- 午前80問(4択)
- 午後大問選択解答（必須の大問もある）
- 午後大問1,8必須、大問2～7から4問選択、問9～13から1問選択
- 試験料5,700 円

ここまで読んで、勉強法も知りたいよ！って方は
【忙しい人向け】基本情報技術者試験勉強法（まだ完成してません...ごめんなさい）
も参照いただけると幸いです。
【Laravel】複数のテーブルをJOIN→GROUP BYでグループ化→特定のレコードを取得

## 前提条件
親テーブル：classes

|id  |name  |
|--:|--:|
|1  |A  |
|2  |B  |
|3  |C  |

子テーブル：students

|id  |number  |name  |class_id  |
|--:|--:|--:|--:|
|1  |1  |AAA  |1  |
|2  |2  |BBB  |1  |
|3  |1  |CCC  |2  |
|4  |2  |DDD  |2  |
|5  |1  |EEE  |3  |
|6  |3  |FFF  |2  |
やりたいこと：各クラスの中で出席番号(number)が一番最後の生徒のデータを取得
MySQL

## SQL


```
SELECT * FROM classes 
    LEFT JOIN students 
    ON classes.id = students.class_id
WHERE students.number IN(
    SELECT MAX(students.number) 
    FROM students 
    GROUP BY students.class_id
);
```

## Laravel SQL直書き

```
$sql = 'students.number IN(
    SELECT MAX(students.number)
    FROM students
    GROUP BY students.class_id
)';

$student = DB::table('classes')
    ->leftJoin('students', 'classes.id','=','students.class_id')
    ->whereRaw($sql);
```

## Laravel サブクエリ

```
$student = DB::table('classes')
    ->leftJoin('students', 'classes.id','=','students.class_id')
    ->whereIn('students.number', function($sub) {
        $sub->from('students')
            ->select(DB::raw('max(students.number)'))
            ->groupBy('students.class_id');
    });
```
railsでサジェスト機能を実装してみた


railsでサジェスト機能を実装した時のメモ🍣

autocomplete系のgemが軒並みメンテされていなかったので、jquery-uiで実装していきます。

## 動作環境
rails 5.2.2.1
jquery-ui-rails 6.0.1


# やること
`company`属性を持つ`User`というモデルを想定し、
User作成画面で`company`のテキストフィールドに入力した際、
既にDBに存在するデータをもとに候補をサジェストする機能を実装します😎

こういうやつ↓
![サジェスト.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258211/04b39003-1109-eefa-1fd4-a6c55ca3b318.gif)
## Gemfile

Gemfileに下記を追加し`bundle install`

```ruby:Gemfile
gem 'jquery-ui-rails'
```

```bash
bundle install
```

## application.js
下記を追加

```javascript:/assets/javascripts/application.js
//= require jquery-ui/widgets/autocomplete
```

## application.scss
下記追加

```scss:/assets/stylesheets/application.scss
 @import "jquery-ui/autocomplete";
 @import "jquery-ui/theme";
 @import "jquery-ui/menu";
```

筆者環境だと、theme、menuを外すと表示が崩れました🤔

## routes.rb

サジェストの配列を返すルートを追加します。

```ruby:routes.rb
  resources :users do
    get '/autocomplete_company/:company', on: :collection, action: :autocomplete_company
  end

```

## モデル

前方一致検索のscopeを追加します。

```ruby:user.rb
  # 前方一致検索
  scope :by_company_like, lambda { |company|
    where('company LIKE :value', { value: "#{sanitize_sql_like(company)}%"})
  }
```

## コントローラー

サジェストの候補を返すaction追加
受け取ったパラメータをもとにサジェストしたい文字列の配列を返すようにします。

```ruby:user_controller.rb
  def autocomplete_company
    # params[:company]の値でUser.companyを前方一致検索、company列だけ取り出し、nilと空文字を取り除いた配列
    companies = User.by_company_like(autocomplete_params[:company]).pluck(:company).reject(&:blank?)
    render json: companies
    # レスポンスの例: ["てすと１会社","てすと２会社","てすと３会社"]
  end

  private

    def autocomplete_params
      params.permit(:company)
    end
```

## ビュー

autocompleteのsourceに
サジェスト候補の配列を取得する関数をセット。

```slim:_form.html.slim
= form_with(model: @user, local: true) do |form|
 .form-group
  = form.label :company
  = form.text_field :company
  / id='user_company'で生成される

javascript:
  $(function() {
    const dataList = function(request, response) {
      $.ajax({
        url: '/users/autocomplete_company/' + request.term,
        dataType: 'json',
        type: 'GET',
        cache: true,
        success: function(data) {
          response(data);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
          response(['']);
        }
      });
    }

    // #user_companyの部分は必要に応じてidなり指定してください
    $('#user_company').autocomplete({
      source: dataList,
      autoFocus: true, // 自動的に先頭の項目にフォーカスするか
      delay: 300, // 入力してからサジェストが動くまでの時間(ms)
      minLength: 2 // 2文字入力しないとサジェストが動かない
    })
  });

```

テキストフィールドの内容に応じて、動的に内容を変える必要がなければ
dataListにサジェストしたい文字列の配列を直接入れればOKです！

```slim
javascript:
  $(function() {
    const dataList = ["こうほ１","こうほ２"];
  });
```

# まとめ
jquery-uiを使って、サジェスト機能を実装しました。
今回は説明のため、Viewに直接javascriptを書いてますが
別ファイルにしたり、ヘルパーを切り出したりすると良いと思われます☺️

間違っているところがあればご指摘ください！


[autocompleteのドキュメント](https://api.jqueryui.com/1.10/autocomplete/)
【Linux】Could not resolve hostname hogehoge: nodename nor servname provided, or not knownって出てSSH接続出来ない

## Could not resolve hostname hogehoge: nodename nor servname provided, or not known

いつもの様に人のPCの設定をしていたらこんなメッセージ。

## やろうとしていた事

```
ssh hogehoge
```

↑のコマンドで123.123.12.123（例です）というIPアドレスに接続する
ポートも指定する。
しかし設定を終えてコマンドを叩くと冒頭のメッセージ。

## 解決

hostsにIPアドレスを記述していなかったので、

```
vi /etc/hosts
```

で追記。
無事に接続できる様になりました。

## 補足

今回やりたかった事をするには

```
~/.ssh/config
```

```
/etc/hosts
```

それぞれに設定の記述が必要。

Could not resolve hostnameって出てるので、
エラーメッセージ通りの間違いでしたね。
pythonによるwavファイル読み込み

[PythonのWaveモジュールを使ってwavファイルを編集する](https://qiita.com/niisan-tokyo/items/d25dada3fa9903862260)の記事の以下のコードをコピペしたら、エラーが出てしまいました。

```python:pywave.py

import wave
import struct
from scipy import fromstring, int16

# ファイルを読み出し
wavf = '/data/input/test.wav'
wr = wave.open(wavf, 'r')

# waveファイルが持つ性質を取得
ch = wr.getnchannels()
width = wr.getsampwidth()
fr = wr.getframerate()
fn = wr.getnframes()

print("Channel: ", ch)
print("Sample width: ", width)
print("Frame Rate: ", fr)
print("Frame num: ", fn)
print("Params: ", wr.getparams())
print("Total time: ", 1.0 * fn / fr)

# waveの実データを取得し、数値化
data = wr.readframes(wr.getnframes())
wr.close()
X = fromstring(data, dtype=int16)

```
```
threshold.py:25: DeprecationWarning: The binary mode of fromstring is deprecated, as it behaves surprisingly on unicode inputs. Use frombuffer instead
  X = fromstring(data, dtype=int16)
```

fromstringはunicode入力のときに何かすごい挙動するからやめて、みたいな事のようです。そして、frombufferを使え、と。
調べてみると、frombufferはnumpyのメソッド(?)のようなので、importにnumpyを入れて、fromstringはnp.frombufferにします。

```python:pywave.py

import numpy as np
import wave
import struct

# ファイルを読み出し
wavf = 'test.wav'
wr = wave.open(wavf, 'r')

# waveファイルが持つ性質を取得
ch = wr.getnchannels()
width = wr.getsampwidth()
fr = wr.getframerate()
fn = wr.getnframes()

print("Channel: ", ch)
print("Sample width: ", width)
print("Frame Rate: ", fr)
print("Frame num: ", fn)
print("Params: ", wr.getparams())
print("Total time: ", 1.0 * fn / fr)

# waveの実データを取得し、数値化
data = wr.readframes(wr.getnframes())
wr.close()
X = np.frombuffer(data, dtype=np.int16)
```

これで無事動きました。
【忙しい人向け】基本情報技術者試験リンク集

# リンク集
- [【忙しい人向け】基本情報技術者試験の必要性](https://qiita.com/keit0728/items/ca58f2a20f4ede0ad6c7)

- [【忙しい人向け】基本情報技術者試験概要](https://qiita.com/keit0728/items/397f3883986fb8ba64c8)
- 【忙しい人向け】基本情報技術者試験勉強法(まだ完成してません...ごめんなさい)
formタグを使った名前検索機能ーPHP

#formタグを使った検索機能ーPHP

データベースに保存されているものをformタグを使用して検索する方法。
inputタグに入力された文字列を指定しているテーブルのカラムに対して検索をかけ、一致するものを表示させる。
今回は部分一致での検索。

例）
・田中
・佐藤
・鈴木
・木村

「木」という文字列を検索したときの結果は
「鈴木」「木村」が結果として返ってくる。

その他前方一致、後方一致、完全一致に関しては下記記事参考
https://alunote.hatenablog.com/entry/2018/09/12/143652

通常部分一致をの検索をかける際は下記の書き方で実行できる。

```php:
$search = $_GET['search'];
$sql = "SELECT * FROM users WHERE name LIKE '%$search%'";
```

この場合、「％」を入れて検索した場合、全件取得される。
文字列として「％」を含むものを検索できなくなってしまっている・
**「％」も文字として検索するためにエスケープする必要がある。**


```php:select.php
<?php
$dbh = new PDO('mysql:host=localhost; dbname=xxxxxx; charset=utf8;', 'xxxxxx', 'xxxxxx');
$search = addslashes($_GET['search']);
//検索された文字列の前にバックスラッシュを入れてエスケープする
$sql = "SELECT * FROM 'テーブル名' WHERE 'カラム名' LIKE :search";
$stmt = $dbh->prepare($sql);
$stmt->bindValue(':search', '%' . addcslashes($search, '\_%') . '%', PDO::PARAM_STR);
//addcslashesの第二引数にエスケープの対象となる（バックスラッシュを入れる）文字列を入れる
$stmt->execute();
?>
```
**addslashes関数**
>エスケープすべき文字の前にバックスラッシュを付けて返します。 エスケープすべき文字とは、シングルクォート('), ダブルクォート("),バックスラッシュ (\) ,NUL (NULL バイト) です。

**addcslashes関数**
第一引数にエスケープしたい文字列、第二引数にエスケープの対象となる文字列を入れる。

この方法で例えばデータベースに「％」や「_」を含むデータがあったとしても文字列を認識して検索することができる。
【Microsoft Intune】Graph API で iPhoneの緯度経度を取得してみました！

皆さんこんにちは、アイネットテクノロジーの上口です。
今回 Microsoft Intune 及びDEP管理されているiPhoneの緯度経度をGraph APIで取得してみました:v:

まず、はじめにDEPですが、AppleのDeviceEnllomentのことを言います。
参考URL: https://support.apple.com/ja-jp/HT204142

企業がiPhoneをAppleまたはキャリアから購入する際に、AppleのMDMサーバーにデバイスを登録する
ことができます。

このDEPを使用し、紛失モードというモードをIntuneでオンにすることで紛失したiPhoneの場所を
特定することができます。

管理者がIntuneからiPhoneの場所を特定することは可能ですが、デバイスを探す人は恐らく無くした本人。
本人に緯度、経度を伝えてあげればブラウザなどで確認することができますよね。

では、早速。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/194fd5d4-18c8-052b-4cc7-37432ec328bd.png)

紛失モードにすると、下記のように地図に表示されます。（あえて小さくしておきます。。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/20eacd4d-bd09-d778-8c7f-eca545616d9c.png)


では、そろそろ本題のGraphAPIを使用して緯度、経度を検索してみましょう。

【前提条件】
・対象の iOS が iOS 9.3 以降である 
・対象の iOS デバイスが、監視モードである 
・対象の iOS デバイスが、Intune に企業所有として登録されている 
・対象の iOS デバイスが、紛失モードである 

 

【手順】
1. Intune の管理者アカウントで Azure ポータル (https://portal.azure.com) にサインインする
2. 画面左から [すべてのサービス] - [Intune] をクリックする 
3. [デバイス] - [すべてのデバイス] をクリックする 
4. デバイスの一覧から紛失した対象の iOS デバイスをクリックする 
5. [ハードウェア] をクリックする 
6. [Intune デバイス ID] の値を確認する 
7. PowerShell を管理者として実行する 
8. 以下のコマンドを実行して、Intune 用 PowerShell モジュールをインストールする 

【コマンド】
Install-Module -Name Microsoft.Graph.Intune 
$deviceid = "＜上記 6. で確認をした Intune デバイス ID＞" 
$result = Invoke-MSGraphRequest -HttpMethod:GET -Url"deviceManagement/manageddevices('$deviceid')" 
$result.deviceActionResults.deviceLocation

■モジュールインストール！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/7e2519d1-13a6-5faa-47da-626b9bb7bd84.png)

■サインイン完了後、アクセス許可を確認し、「組織に同意する」にチェックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/dfac162d-1dc8-4ac5-1d6f-b0598d51649a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/00927c43-2c78-10df-d10e-d6172157c18d.png)

以上で取得できます。
そんなに難しくないのでIntune & DEP環境をお持ちの方は是非お試しください。

これからもブログ更新していきますのでよろしくお願いします。
【忙しい人向け】基本情報技術者試験の必要性

# 誰向け？
基本情報技術者試験？意味あるなら受けたいけど時間がないって人向け。
受ける意味、概要についてさらっと説明します。

# 受けるべき？
###受けるべきです！！！
####理由
- 給料があがる（会社によって資格補助がある）
- IT関連の仕事に就きやすい（持ってない人より持ってる人の方が採用したくなるよね）
- ITスキルを身につけるための足掛けとなる（ITの仕事に就きやすい→仕事を通じてITスキルが身につく）

ここまで読んで基本情報技術者試験を受ける気になった方は、[【忙しい人向け】基本情報技術者試概要](https://qiita.com/keit0728/items/397f3883986fb8ba64c8)にも目を通してみてください。
[養老乃瀧ハッカソン2019]ひたすらビールを注文するコースターを作った

# 目次
- はじめに
- 機能概要
- 実装コード
- 感想と反省点

# はじめに
◆飲み会で、周囲の人のグラスが空いていたら、「何か飲まれますか？」と聞いて飲み物を注文せねばならぬ。
◆俺はただ、ビールが飲みたいんだ！飲む物は決まってるんだから注文せずにズッて持ってこいや！

って思うこと、ありませんか？

少なくとも、私は常々思ってます。
なので、空いたグラスをドッと置いたらビールがズッと来るデバイスを作れないだろうかと思って、実際に作りました。
また、居酒屋にあると嬉しい(主に私が)ので、養老乃瀧ハッカソン2019で発表してきました。

# 機能概要
タイトル：自動お酒注文コースター「飲ま飲まWay！」
![DSC_0037_copy.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/ab7426c6-e5b7-6c28-1504-2cf10307dc48.jpeg)

<img width="589" alt="コメント 2019-10-28 224058.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/d1b82244-0f75-4e56-98b7-ff876dd67b80.png">


☆使い方☆
1.コースターに空いたグラスを置く
![DSC_0028_copy.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/ce0ad85d-6fa5-b95c-8e27-520f5f931739.jpeg)

2.LEDが光るので、店員が飲み物を提供！
<img width="617" alt="コメント 2019-10-28 224017.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/d73d938b-31a3-b79b-a888-ae95e42cd37f.png">

3.**飲む！**

# 実装コード

```javascript:nomanomaWay.js
'use strict';

// Obniz用定数
var Obniz = require('obniz');
var obniz = new Obniz('yourObnizNumber');
var obniz2 = new Obniz('yourObnizNumber');
var stringWeight;

// Obniz関数
obniz.onconnect = async function ()
{
    obniz.display.clear();
    // ロードセル
    var hcsr04 = obniz.wired("hx711", { gnd: 0, dout: 1, sck: 2, vcc: 3 });

    while (true)
    {
        hcsr04.offset = 88815;
        hcsr04.scale = 88925;
        var val = await hcsr04.getValueWait(1);
        stringWeight = Math.abs(roundFloat(val, 4) * 10000);
        console.log(Math.abs(roundFloat(val, 4) * 10000));
        await obniz.wait(10);
        if (Number.isInteger(stringWeight) == false)
        {
            hcsr04.powerDown();
            obniz.close();
        };
    }
    function roundFloat(number, n)
    {
        var _pow = Math.pow(10, n);
        return Math.round(number * _pow) / _pow;
    }
}

obniz2.onconnect = async function ()
{
    obniz2.display.clear();
    // ソレノイド
    var solenoid = obniz2.wired('Solenoid', { gnd: 0, signal: 1 });
    await obniz2.wait(3000);
    if (obniz.connectionState == 'closed')
    {
        solenoid.on();
        await obniz2.wait(3000);
        solenoid.off();
        obniz2.close();
    }
}
```

# 感想と反省点

実際に作ったとき、これは賞とれるだろ！と思ったのですが、取れませんでした。
原因を自分なりに考えた時、養老乃瀧ハッカソン2019のテーマが「皆が笑顔になる」ことがメインだったようで、それとはちょっと合わなかったのかなと。
また、ほかの作品たちがインパクトありまくりで、印象に残らなかったというのもあったのかなと。~~ぶっちゃけ自分の作品地味だし~~

ただ、結構悔しかったので、リメイクしてリベンジしたいと思ってます。
改善案としては、コースターを光らせたり、なにか音を出したりすることを考えてます。

なお、個性的な作品たちの詳細は、以下サイトをチェックだ！
・[protopedia](https://protopedia.net/)
※タグ検索で 'yorohack2019' を入力してね！
標本平均の分散が母分散/標本サイズとなることを数値実験で確認する

#背景
[標本平均の期待値が母平均となることを数値実験で確認する](https://qiita.com/jajagacchi/items/b94a13f41679de67ed4f)の続編です。

今回は標本分散$s^2$が$\sigma^2/n$となることを数値実験で確認します($\sigma^2$:母分散、$n$:標本サイズ)。

#数値実験
確率分布関数は一次元の一様分布[-1,+1)とします。標本サイズnをパラメータとし、1000回抽出を繰り返し、標本平均の分散値を計算しました。

```c++
#include <iostream>
#include <random>

int main(int argc, char **argv)
{
        std::mt19937 mt(0);
        double a = -1, b = 1;
        std::uniform_real_distribution<double> r(a, b);

        int num_of_sample = atoi(argv[1]);//標本サイズ
        int Iter = 1000;//試行回数

        double mean = 0;
        double var = 0;
        for (int iter = 0; iter < Iter; iter++)
        {
                double avr = 0;//標本平均
                for (int n = 0; n < num_of_sample; n++)
                {
                        double val = r(mt);
                        avr += val / (double)num_of_sample;
                }
                mean += avr / (double)(Iter + 1);
                var += avr * avr / (double)(Iter + 1);
        }
        var -= mean * mean;
        std::cout <<  num_of_sample << " " << var << std::endl;

        return 0;
}
```

![plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/c80e0d9a-055e-b663-fb10-08f0077a152f.png)
実線が$\sigma^2/n$です。ほぼ理論曲線に乗りました。

#まとめ
標本平均の分散が母分散/標本サイズとなることを数値実験で確認することが出来ました。次回は標本分散の期待値を考えたいと思います。
次回：[標本分散の期待値が母分散×(標本サイズ-1)/標本サイズとなることを数値実験で確認する](https://qiita.com/jajagacchi/items/4b985e7c3d771d95d6f8)
【CodeBuild】'NoneType' object has no attribute 'get' 

## エラーの内容
CodeBuildでCloudformationで使用するアーティファクトを作成しようとしたところ、以下のエラーが発生した。

```
'NoneType' object has no attribute 'get' 
```

## 原因

単純に、Cloudformationのテンプレートが間違っていると発生するエラーのようだ。
以下を参照

[AttributeError: 'NoneType' object has no attribute 'items' on malformed CloudFormation ](https://github.com/aws/aws-cli/issues/2307#issuecomment-267715808)

フォーラムでも叩かれているけどこのエラー文は本当にミスリーディングを引き起こすからやめてほしい・・・
The benefits of IT outsourcing

![outsourcing.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425411/cca7fdff-bb59-a48a-e30e-605f0e8f9788.jpeg)

Today IT outsourcing has become a common practice among companies from all over the world. The global market size of IT outsourcing services reached $85.6 billion in 2018. There are many reasons for IT outsourcing, from the ability to reach a more diverse talent pool to cutting costs.

![IT Outsourcing benefits.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425411/e214b5e8-249a-721f-686a-eafe9150cd03.jpeg)

IT outsourcing is the practice of sub-contracting or “farming out” some tasks related to information technologies. Companies engage external resources to perform certain operations which helps them streamline the workflow, and save time and money.

Technology outsourcing opens up a whole world of possibilities for companies and allows them to not be limited to a particular location or market. It became a panacea for many growing companies that require software development services and highly experienced professionals.

I suggest you should take a look at this [article](https://mlsdev.com/blog/it-outsourcing) to get full information about the benefits of IT outsourcing.
Rails5.2 + Vue.js + Dockerでプロジェクトを作成

##はじめに

Railsを使っていてVueも一通り学んだのでRailsとVueを使えるように環境構築してみようと思い勉強してみたことをアウトプット。

Rubyのバージョンは2.5.3
Railsのバージョンは5.2.3
DBはMysqlを使用

Railsのプロジェクトを作成するディレクトリを事前に作成しておく
```$ mkdir <任意のフォルダ名>```
フォルダを作成したら作成したディレクトリに移動しておく

##Docker用のファイルの作成
Dockerのコンテナを作成するためのファイルを作成

Dockerfile
docker-compose.yml
Gemfile
Gemfile.lock
の４つのファイルを作成する。

```java:Dockerfile
FROM ruby:2.5.3

RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - && apt-get update && \
    apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/*

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev

RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn

RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
    apt-get install nodejs

RUN yarn add node-sass

RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app

```

```java:docker-compose.yml
version: '3'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true
  db:
    image: mysql:5.7
    volumes:
      - db-volume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
volumes:
  db-volume:
```
```java:Gemfile
source 'https://rubygems.org'
gem 'rails', '5.2.3'
```
Gemfile.lock
はbuildした後に自動的に記述されるので空にしておく。（ファイルは必要）

この４つのファイルを作成し、先ほど作成したディレクトリに置く。

##Railsプロジェクトの作成

次にRailsのプロジェクトを作成するため次のコマンドを実行
```$ docker-compose run web rails new . --force --database=mysql```
(rails newの . は現在いるディレクトリにそのままプロジェクトを作成するというもの)

プロジェクトの作成が終わったら```docker-compose ps```でコンテナが作成されているか確認。
次にRailsプロジェクトのdatabase.ymlを編集します。

```config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db
```
passwordとhostの部分をdocker-compose.ymlの記述と合わせます。


```$ docker-compose up```コマンドでコンテナを立ち上げ、localhost:3000に接続し、RailsのHello World画面が表示されれば無事成功です！

##Vue.jsの導入

vue.jsをRailsで使用できるようにするためにまずはWebpackerの導入が必要。Gemfileに以下を追加します。

```java:Gemfile
gem 'webpacker'
```
記述したら

```$ docker-compose run web rails webpacker:install```を実行

自分の場合、Gemfileの記述を
```gem 'webpacker', github: 'rails/webpacker'```
とするとyarnエラーが出てインストールができませんでした。

インストールが完了したらいろいろRailsのプロジェクトにファイルが追加されると思います。

次にVueをインストールしていきます。
```$docker-compose run web rails webpacker:install:vue ```

これでVue.jsの導入が完了しました。


##vue.jsファイルのビルド

次にVue.js関連のコンポーネントをJavascriptにコンパイルするため 
```$ docker-compose run web bin/webpack```コマンドを実行します。

RailsのViewsファイルに
<%=javascript_pack_tag 'hello_vue'%>と記述し問題なく表示されていれば成功です！


参考
[dockerでrails+vueの環境を作ったので解説](https://qiita.com/hogehoge1234/items/30fa0b3bc9b643400414)
[Rails5.2 + Docker環境にVue.js (Webpacker) を導入する](https://remonote.jp/rails-docker-vuejs-construction)
S3のChecksum比較でちょっとハマったのでメモ。

いつもの如く、ブログからの転載です。
https://munchkins-diary.hatenablog.com/entry/2019/10/28/230924
最近あんまり書いてないですが、そろそろ再開したい。

S3上のファイルのチェックサムを取得する方法でハマりやすいとこと、下の方におまけでJavaでfileのチェックサムを計算する方法を書いておきました。

誰かの役に立てば幸いです。
(なおあまり)

# S3のチェックサムを比較したい
数GBのファイルをS3に挙げるような処理を書いていて、後続処理の失敗などでリトライしたいというのがあった。

この場合、ファイルをアップロードし直すのはムダだが、移行元ストレージ内の対象ファイルが変更にされている可能性もある。
したがって、すでにS3上に`完全に同じ`ファイルがあるときだけアップロードをリトライしたい。

この場合、チェックサムを比較するのが楽なので、S3の`getObjectMetaData` APIを利用して以下のようにコードを書いた。

```java
 private boolean shouldSkip(String bucketName, String key, String md5CheckSum) {
      try {
        ObjectMetadata meta = s3Client.getObjectMetadata(bucketName, key);
        if (meta == null || meta.getContentMD5() == null) {
          log.info("meta data not exist for the file {} in bucket {}", key, bucketName);
          return false;
        }
        log.info(
            "Checksum of existing file is {} and present file checksum is {}",
            meta.getContentMD5(),
            md5CheckSum);
        return meta.getContentMD5().equals(md5CheckSum);
      } catch (SdkClientException e) {
        log.error("Exception thrown while validating the checksum of the file {}", key, e);
        return false;
      }
    }
```

しかし、どうもうまく行かない。
`ObjectMetaData#contentMD5`がどうしてもNullになってしまうのだ。

調べたところ、S3における既存オブジェクトのチェックサムはcontentMD5ではなく、`Etag`に付与されるらしい。

じゃあcontentMD5は何に使うかと言うと、更新時にHTTPヘッダに付与されて、S3内での改ざん確認（正しい使い方）に使うため、getでオブジェクトを取得する時は返されないのだとか。

したがって、S3から落として来たファイルのチェックサムを知りたい時はEtagと比較する必要がある。

こんな感じ。

```java
    private boolean shouldSkip(String bucketName, String key, String md5CheckSum) {
      try {
        ObjectMetadata meta = this.s3Client.getObjectMetadata(bucketName, key);
        if (meta == null || meta.getETag() == null) {
          log.info("meta data not exist for the file {} in bucket {}", key, bucketName);
          return false;
        }
        log.info(
            "Checksum of existing file is {} and present file checksum is {}",
            meta.getETag(),
            md5CheckSum);
        return meta.getETag().equals(md5CheckSum);
      } catch (SdkClientException e) {
        log.error("Exception thrown while validating the checksum of the file {}", key, e);
        return false;
      }
    }
```

これならちゃんと動く。 誰かの役に立てば幸いです。


# おまけ Javaでのチェックサム確認方法

チェックサムでググって飛んで来た人のために一応書いておくと、Javaでチェックサムを計算する方法はこんな感じ。

```java
  public static String checkMd5Checksum(File file) {
    try (BufferedInputStream is = new BufferedInputStream(new FileInputStream(file))) {
      return DigestUtils.md5Hex(is);
    } catch (Exception e) {
      // Not likely to occur.
      log.error(
          "ERROR Happened while calculating the check sum for file {}", file.getAbsolutePath(), e);
      return "NOT FOUND";
    }
  }
```

sha256なら `DigestUtils#md5Hex`を `DigestUtils#sha256Hex`に変えるだけ。

以上、メモでした。
Eclipse MicroProfileとは

# 概要
前回の[記事](https://qiita.com/omix222/items/923d788d6ce76e179d6a)では、Eclipse MicroProfileの始め方をご紹介しました。今記事では、そもそもEclipse MicroProfileとはなにか？を紹介します。


## 生まれたきっかけ

もともとはJavaEEの仕様策定のプロセスが遅い、リソースを十分に供給できていないと危機感を持った複数のベンダーとJavaコミュニティによって生まれました。

特徴としては、JAX-RSやCDIなど、JavaEEの中で慣れ親しんだ仕様を一部取り込みつつ、マイクロサービスアーキテクチャで必要な機能を独自で取り込んでいくというものとなります。

<img width="375" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113217/85c57b1c-9421-f3b3-46ec-95089cc1a42d.png">

※現在の[公式サイト](https://microprofile.io/resources/)のWhitePaparから抜粋

その後、2017年1月ごろ、Eclipse Foundation傘下に正式に加わった物となります。

https://www.publickey1.jp/blog/17/javamicroprofileeclipse.html

## 仕様に準拠しているプロダクト、実装

これも上述のホワイトペーパーを抜粋すると以下の通りとなっています。

<img width="370" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113217/93c297b9-7604-4c69-6810-96ec032ace07.png">

ここで注目すべきは以下の通りです。

- JBoss EAPはJavaEEサーバにも関わらず、MicroProfileにも準拠している
- Open LibertyはJavaEE のWebProfile仕様準拠にも関わらず、MicroProfileにも準拠している
- 日本国内のJavaEEサーバベンダーで対応しているのは富士通社のみ

## Eclipse MicroProfile3.0の仕様一覧

最後に、簡単にではありますが、各種仕様について一言ずつ説明していきます。

### Eclipse MicroProfile Config
クラウド上やマイクロサービスとしてアプリケーション設定をしやすくします。
具体的には、アプリ内に設定をハードコードしてしまうと、環境によってアプリを都度ビルドする必要が出てきてしまうため、起動時の引数や、環境変数の内容で設定を上書きできるようにすることができます。SpringBootでも同じような機能がありますね。

### Eclipse MicroProfile Fault Tolerance
マイクロサービスとしてアプリケーションを作る際に、別のサービスとの関連と、ビジネスロジックを分離することを目的とした機能です。具体的な機能としては、TimeOut、RetryPolicy、Fallback、Bulkhead、Circuit Breakerなどがあります。

### Eclipse MicroProfile Health
マイクロサービスとして呼ばれるサービスとして、そのサービスが応答できる健康な状態かどうかを示す機能を提供する仕様です。Up、Downだけでなく、捕捉情報も含めて返却することができます。

### Eclipse MicroProfile JWT Authentication
OpenID Connect (OIDC) と JSON Web Tokens (JWT）を使って認証機能を提供します。
role based access control (RBAC)で作られるマイクロサービスとして提供されることを前提としています。

### Eclipse MicroProfile Metrics
運用時に必要なメトリクスを提供する機能を示した仕様です。


### Eclipse MicroProfile OpenAPI
マイクロサービスをOpenAPI仕様であるOpenAPI v3 specificationに則るAPIドキュメンテーションを出力できるような機能を提供する仕様です。

### Eclipse MicroProfile OpenTracing
マイクロサービスでは、どのサービスが遅延しているか、どのサービスがどんな頻度でエラーとなっているかを可視化しておくことが重要です。トレース結果を出力することができます。

### Eclipse MicroProfile Rest Client
JavaEEのJAX-RS 2.1 APIのRest Client作成をベースとしてよりtype-safeに実装することができるようにする機能を提供する仕様です。

### JavaEEから継承している仕様
- CDI 2.0
- JAX-RS 2.1
- JSON-B 1.0
- JSON-P 1.1
- Common Annotations 1.3

##　まとめ
今回はコード無しで、Eclipse MicroProfileについて説明しました。
UberJarの話とかすっとばしましたが、なんとなく全体像は分かったのではないでしょうか。

JavaEEで慣れ親しんだ仕様＋マイクロサービスで必要な機能ということで有用なものもあったかと思います。個人的にはConfigとかは、マイクロサービス関係なく、どんなアプリでもこの機能があると開発が楽になるものと思うので、他でも楽に使えると良いかと思いました。
同じID内で最大のものを表示するときのEntityFramework

SQLDatabaseでシステム運用していたが、処理が遅くてエラーになってしまった。
クエリはこんな感じ

```
C#

var query = context.TBL_A.GroupBy(p => p.Type).Select(g => g.OrderByDescending(p => p.Date)
.FirstOrDefault()

```

出典
https://stackoverflow.com/questions/16273485/entity-framework-select-one-of-each-group-by-date


TBL_Aに対してType列でGroupByして、日付の降順に並び替え、FirstOrDefaultで1行目を取得します。これにより、同一値内の最大日付のレコードのみ取得することができます。
SQLDatabase、Basicプランで運用していましたが、対象テーブルが5000レコードを超えたくらいでタイムアウトエラーが発生してしまいました。30秒以上返ってこないでやんの。。

なので、修正してみました。

```
C#

var query = context.TBL_A.Wherey(x => !context.TBL_A.Any(s => s.Type == x.Type && s.Date > x.Date))


```

参考
http://labs.timedia.co.jp/2014/10/selecting-max-record-in-group-by.html

　
条件は同一のTypeかつDateが小さいもの。!context.TBL_A.Any でNot Exists句になるので、一番大きいものだけが取得できます。素晴らしい。

パフォーマンスも秒でかえってくるようになりました。
inteliJのブレークポイントで変数の値を変更する方法

#環境
Intelij
Java(Java以外でもできるかもしれないけど未確認)

#手順
下のようなコードを書くと、当然"Hello World"と表示されますが、
strに"ハローワールド！"という別の値をデバッグ中は入れたいとします。
<img width="709" alt="スクリーンショット 2019-10-28 22.51.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230281/378c10f1-398b-a7f6-287e-ef9ad54931e2.png">


そんなときはブレークポイントを設定
→右クリック
→More(command + shift + F8)
<img width="891" alt="スクリーンショット 2019-10-28 22.52.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230281/ba390ccc-5c54-286a-33c3-714721086a5a.png">

BreakPointsウィンドウが出るので
Evaluate and log にチェック
→strに値を代入
→（ブレークポイントで止めたくない場合）Suspendのチェックを外す
<img width="969" alt="スクリーンショット 2
019-10-28 22.52.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230281/57099699-bc5b-ce0f-d7b7-363487385cbe.png">

この状態でDebug実行すると
<img width="709" alt="スクリーンショット 2019-10-28 22.53.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230281/ff698486-5002-7ebe-bfb7-5fa0505af320.png">

"ハローワールド！"と出ました。
二回出てるのはEvaluate and "log"によるログ出力のためです。

値の代入以外にも、メソッドの実行なども可能です。
特別な条件のときにしか実行されないコードのデバッグなどに使えると思います。
今日から学んできたことを毎日ブログにしていきたいと思います！

　さて、今日から毎日学んだことをブログに記していきたいと思う。

　そのまえに私の今現在の状況とプログラマーを目指すきっかけについて記していこうと思う。私は今現在、某国立大学で化学系のことを学んでいる。しかし、インターンシップなどに参加しても、どうも専攻の職に興味などが一切湧かなかった。それもそのはず、高校から大学までレールの上をただ何も考えずに歩んできたからだ。高校・大学では、何となく受かりそうだから受けてきた。大学に行くのも惰性で行き、人生つまんねえなあと思う日々。アニメ的な展開起きないかなと考える日々。そんな人生を変えることは起きないのも当たり前だ。何にも行動せず、ただ過ぎ行く日々をこなしているからだ。

　というのを毎日考え過ごして来て、これからは多くのことにチャレンジし継続していきたいと思う。きっかけは自分でもあまり覚えていないが、フリーランスになれば家で仕事できるなどそんな甘えた考えだろう。話は戻り、私が今現在継続していることは、プログラミング学習だ。つい一週間位前から始めている。それに加え、ブラインドタッチを三日前から始めている。今、ブログを書くのもブラインドタッチだ。全然思った文字も打てないし、時間もかかり、少しもどかしい気持ちだ。

　前置きが長いな。すみません。今日したことは、ドットインストールのBoostrapを1～7までこなした。プログラミングでインプットしたのはこれだけだ。すごい少ない。自覚はしているが、どうにも身が入らなかった。この原因としては就職について最近焦り初めており、今日はキャリアカウンセリングというのを受けてきた。これは、就職相談みたいなのだ。利用してみた感想としては、「めちゃくちゃ焦りが積もった」この一言につきる。今まで就職について考えてきてないとはいえ、やばいと思った。さらに、今の時期からインターンなどを経て早期面接とか受けている人がいることいにはとてもびっくりした。周りに動いている人がいないし、地方だからとは言え情報不足だった。このような原因で焦りの思考ループにより身が入らなかった。今日一日解決策を考えているが、現状何も思いつかない。明日も考えよう。

　さて話は戻り、今日は下のような画像のように、学んだ単元のことを要約しながら進めた。<img width="960" alt="無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521326/413de913-1598-eae8-9f20-256d31b8741f.png">

さて、学んだことをアウトプットします。Boostrapによりcssの機能を省ける感じなのかな。br-○やtext-○をhtmlの中に組み込んで省いた感じだ。margin:0 auto;のやり方も覚えた。my-0 mx-autoでいけるみたい。後は高さや幅をhやwで略すのも覚えておきたい。このやり方を22回まで続けよう。

 今回の記事で書きたかったことの半分も書けなかった。文章能力もぜんぜんないし、タイピングが思うようにいかないのが原因だろう。こんな短い文章を書くのにも1時間近く経った。明日からは、もう少し短い文章にして継続していこう。

　明日のTo Do List
・Progate　中級道場　上級道場
・ドットインストール　Boostrap 8～15
・参考になるブログを読む　詳しくは明日書きます。
大学もあるけど明日も一日、頑張りましょう！
別テーブルのSELECT結果で、一括UPDATEしたい（UPDATE ～ SELECT）

備忘録としてメモします。
# SQLの書き方
Table_A の column_1 列と column_2 列を、Table_B の column_x 列と column_y 列の内容で UPDATE したい。
（Table_A と Table_B は、それぞれの ID 列で JOIN される。）

```SQL:記述例
UPDATE Table_A
SET Table_A.column_1 = Table_B.column_x
    ,Table_A.column_2 = Table_B.column_y
FROM Table_A
INNER JOIN Table_B ON Table_A.ID=Table_B.ID
```
# 実例
以下の社員テーブルの「所属課」列を、社員所属テーブルの「所属課」で UPDATE したいとします。
（分かりやすいよう、テーブル名と列名は日本語としました。）
###「社員」テーブル
|社員ID|氏名|役職|所属課|
|:-:|:-------:|:--:|:--:|
| 1 | 田中一郎 |課長|NULL|
| 2 | 鈴木次郎 |係長|NULL|
| 3 | 岡田三郎 |係長|NULL|
| 4 | 中田花子 |課長|NULL|
| 5 | 太田理恵 |課長|NULL|
| 6 | 田村絵里 |係長|NULL|

社員テーブルの「所属課」列が全て NULL（未設定）になっています。
この「所属課」列を、以下の「社員所属テーブル」からデータを引っ張ってきて UPDATE します。
###「社員所属」テーブル
|社員ID|所属課|
|:-:|:--:|
| 1 | 営業課 |
| 2 | 総務課 |
| 3 | 企画課 |
| 4 | 総務課 |
| 5 | 企画課 |
| 6 | 営業課 |
![img_sql1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520210/d9600e66-26a6-6d6f-4e84-f7320f555e82.png)
### SQL

```SQL:更新スクリプト
UPDATE [社員]
SET [社員].[所属課] = [社員所属].[所属課]
FROM [社員]
INNER JOIN [社員所属] ON [社員].[社員ID]=[社員所属].[社員ID]
```

# 感想
INSERT ～ SELECT はわりと分かりやすいのですが、UPDATE　～　SELECT　は、
`UPDATE [テーブル名] SET [列名]=xxx`
の後ろに、
`FROM [テーブル名]`
と、同じテーブル名を FROM 句でまた書かないといけないのを、つい忘れてしまいます。
phpメソッドをすげ替える掟破りの技、runkit

# 概要
* phpのrunkitを使うと掟破りのアレコレができる
* strtotime()を叩いた時に-9h分勝手にやるとか

# 使いどころ
* 弊社ブラウザゲームでは開発環境で未来日のデバッグをする時などに。

# 参考ドキュメント
* [PHP:runkit](https://www.php.net/manual/ja/book.runkit.php)
* [PHP5でrunkit](https://qiita.com/rana_kualu/items/43dddf983303a2777f05)

# 実行例
```
// 時間調整
//date()をオーバーライドしてsimulationTimeを返す
runkit_function_copy('date', 'date2');
runkit_function_redefine('date', '$a, $b=null', 'return date2($a, $b ? $b : strtotime("' . $simulationTime . '"));');

//strtotime()をオーバーライドしてsimulationTimeを返す
runkit_function_copy('strtotime', 'strtotime2');
runkit_function_redefine('strtotime', '$a, $b=null', 'return strtotime2($a, $b ? $b : strtotime2(date2("Y-m-d H:i:s", time())));');

//time()をオーバーライドしてsimulationTimeを返す
runkit_function_redefine('time', '', 'return strtotime2("' . $simulationTime . '");');

//DBの時刻も上書きする
Db::Update("set TIMESTAMP = unix_timestamp('{$simulationTime}');");
```

# ハマリどころ
## オーバーライドが使えない
```
strtotime() is an internal function and runkit.internal_override is disabled in file /xxxx/xxx.php
```

* 普通に「runkit.internal_override使えねーよ」って言われた

### 解決方法
#### phpinfoを見てみる
```
Directive	Local Value	Master Value
runkit.internal_override	Off	Off
runkit.superglobal	no value	no value
```

#### iniファイルで設定できる
phpinfo.additional .ini files parsedにパスがある

```
/etc/php.d/runkit.ini

runkit.internal_override On
```

# 雑感
* 非常に強力なので知らない人には意識させない(FWの上位で利用するetc)のが大事
* ただ開発環境のデバッグなどでイベントやキャンペーンを開きたい時に、本番相当の開催データのままデプロイできるのは非常に有用
picoCTF 2019 where are the robots - Points: 100

#問題

https://2019game.picoctf.com/problems

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/9796bc91-1108-9b02-4059-b5dfb7bdcec8.png)

#解いてみた

リンクにアクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/5ec70e45-699d-d025-b039-4e0182640e16.png)

ソースを見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/0d72393f-f3a9-ca2e-6e7d-2ecfb68a8d9d.png)

wiresharkで通信を見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/3dee37ae-8982-14a7-1a9d-2425950cc57a.png)

cookieなどもなさそうです。
問題文をもう一度読んでみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/4908c4dc-7843-dd83-90ab-18bd6b7442ef.png)

イマイチよくわかりません。
ヒントを見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/d6e2b740-3174-e3e4-ef97-e402e0f335a7.png)

？
あなたに というか robotにということでしょうか。
robots.txtか？

```
http://2019shell1.picoctf.com:47235/robots.txt
```

にアクセスしてみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/6d61592a-002f-b1c0-c784-e58815414d6b.png)

```
http://2019shell1.picoctf.com:47235/54e98.html
```

にアクセスしてみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/90024a31-8f58-dd89-2b4f-c3d2b347ae2c.png)

できた。
発火とは?

#はじめに
JavaScriptを習得した人・しようとしている人は、`発火`という単語を必ず聞いたことがあります。
そして、中にはこの言葉に馴染めず、学習が遅れてしまった人もいるでしょう。
本記事では、発火とはどういうものか、なんで発火というのか、について書かせて頂きます。

別ブログにて、書き直したものを公開中です
[https://airesaies.com/2020/05/14/program003/](https://airesaies.com/2020/05/14/program003/)

#内容

##そもそも"発火"とはなんぞや？
発火とは、JavaScriptにおいて***メソッドが実行されること***をいいます。
JavaScriptでは、
①DOMの取得
②処理
③HTMLの操作
という順序でビューを変更しますが、この中で③がメソッドの発火によって行われます。

##どうやったら発火するの？
指定されたクラスに、指定されたイベントを起こすと発火します。
イベントを起こすというのは、例えばクリックする、送信するなどです。
クラスを指定するのは、DOMを取得することにより行えます。

```javascript
var btn = document.querySelector("button");

function Say() {
  console.log("Hello.world");
}

btn.addEventListener("click", Say);
```

例えば上のコードでは、
```var btn = document.querySelector("button");```
でDOMを取得し、btnに代入。（```button```を取得）
```btn.addEventListener("click", Say);```
で発火する条件を指定しています。
```btn```.addEventListener("click", Say);
btnでクラスの指定。
btn.addEventListener(```"click"```, Say);
でイベントを指定しています。
この場合、***button(btn)をクリック(click)すると、関数Sayが実行される***、
***発火***を使って言い換えると、***button(btn)をクリック(click)すると、関数Sayが発火する***
ことになります。

##なんでこんな呼び方に？
はっきりしませんが、一説には'イベントを実行する'という意味の```fire event```を訳したものだそうです。
これでだと訳した方も、原文の方も「もっと正確な言葉があったのでは？」と思ってしまうので、
もしかしたら違う理由があるのかもしれません。
エクセルVBA(マクロ)でシートを１枚のPDFに自動出力する方法

# はじめに
エクセルのシートに帳票を作成したものの、毎回手動でPDF出力するのが面倒なのでVBAで自動的に出力するようにしました。

## ソース

```vb
''' sheetName 保存元のシート名
''' filePath　保存先のファイルパス
Sub PDF保存(sheetName As String, filePath As String)
    Worksheets(sheetName).PageSetup.Zoom = False
    Worksheets(sheetName).PageSetup.FitToPagesWide = 1
    Worksheets(sheetName).PageSetup.FitToPagesTall = 1
    Worksheets(sheetName).ExportAsFixedFormat Type:=xlTypePDF, Filename:=filePath, IgnorePrintAreas:=True, Quality:=xlQualityStandard
End Sub
```

## 解説
### 引数と使い方
第一引数に保存したいシートの名前（文字列）を、第二引数に保存先のパスを入れてください。

### Worksheets(sheetName).PageSetup.Zoom
後述のFitToPagesWideとFitToPagesTallを使う場合にはFalseにする必要があります
https://docs.microsoft.com/ja-jp/office/vba/api/excel.pagesetup.zoom

### Worksheets(sheetName).PageSetup.FitToPagesWide
ページ幅を指定する
https://docs.microsoft.com/ja-jp/office/vba/api/excel.pagesetup.fittopageswide

### Worksheets(sheetName).FitToPagesTall
ページ高さを指定する
https://docs.microsoft.com/ja-jp/office/vba/api/excel.pagesetup.fittopageswide

### Worksheets(sheetName).ExportAsFixedFormat
出力時のフォーマットを指定できます。
今回は、

+ PDFで
+ ファイルパスを指定して
+ 印刷範囲指定をONにして
+ 高品質で
出力するように設定しています。

https://docs.microsoft.com/ja-jp/office/vba/api/excel.workbook.exportasfixedformat
5000件超のリストで条件を指定してアイテムを削除する

CamlQueryは5000件を超えると、RowLimitと条件を指定しても条件で絞り込まれずRowLimitも効かない。
→RowLimitで取得し、For文の中のIf文で条件で絞り込んで削除する。

```
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$ctx.credentials = $creds

try{
 $caml = "<View Scope='RecursiveAll'>
          <ViewFields><FieldRef Name='ID'/><FieldRef Name='Title'></ViewFields>
          <Rowlimit Paged='TRUE'>5000</Rowlimit></View>"
 $list=$ctx.Web.Lists.GetByTitle("リスト表示名")
 $pagePosition = $null

 Do{
   $query = New-Object Microsoft.SharePoint.Client.CamlQuery
   $query.ListItemCollectionPosition = $pagePosition
   $query.ViewXml = $caml

   $listItems = $list.GetItems($query)
   $ctx.Load($listItems)
   $ctx.ExecuteQuery()

   $pagePosition = $listItems.ListItemCollectionPosition

   foreach($item in $listItems){
     if($item["Title"] -eq "削除したい値"){
       $listItems.GetById($item["ID"]).DeleteObject()
       $ctx.ExecuteQuery()
     }
   }
  until($pagePosition -eq $null)

 }
 catch{
       write-host "$($_.Exception.Message)" -foregroundcolor red    
}
$ctx.Dispose()
```

参考
[stackexchange:Deleting over 5000 items SharePoint Online Powershell
](https://sharepoint.stackexchange.com/questions/268996/deleting-over-5000-items-sharepoint-online-powershell)
[SharePoint Online　PowerShell　全アイテム削除](http://blog.kllc.jp/entry/2018/03/05/125355)
Next.jsのDynamic Routing + Static HTML exportを組み合わせて使う

Next.js 9ではDynamic Routingが標準でサポートされ使用感が大きく改善されました。
このDynamic Routingで構築したアプリをexportした場合に一手間必要だったので考慮したことをまとめておきます。

この構成でデプロイを行う際には、ビルド時にデータを全部仕込むか、クライアント側で（APIを叩くなどして）データを仕込むかで大きく対処方法が変わります。

## 今回の想定アプリ

次のようなページを持つアプリケーションを想定します。

```
/
/about
/show/[id]
```

## 1.ビルド時にデータを仕込む方法

exportする際には、`next.config.js`の`exportPathMap`を利用し、出力するファイルの調整を行っていきます。
exportPathMapで、キーにpath、バリューにpage（pageコンポーネントの位置）、query（クエリパラメータ）などの情報をもたせたオブジェクトをそれぞれ作り返り値とします。コードを見たほうが早いでしょう。

```js
const fetch = require('isomorphic-unfetch');

module.exports = {
  exportPathMap: async function() {
    const paths = {
      '/': { page: '/' },
      '/about': { page: '/about' }
    };
    const res = await fetch('https://api.tvmaze.com/search/shows?q=batman');
    const data = await res.json();
    const shows = data.map(entry => entry.show);

    shows.forEach(show => {
      paths[`/show/${show.id}`] = { page: '/show/[id]', query: { id: show.id } };
    });

    return paths;
  }
};
```
> https://nextjs.org/learn/excel/static-html-export/exporting-other-pages より

この際、showのデータを参照するためにAPIを叩いて、結果からexportPathMapのデータを生成します。

## 2. クライアント側でデータを読み込む場合

ビルド後にもデータが増えることが想定されている場合、ビルド時にexportPathMapを使わない選択肢もあります。
exportPathMapを設定しない場合は、次のようなファイルが生成されます。

```
/index.html
/about/index.html
/show/[id]/index.html
```

問題は`/show/[id]/index.html`です。ただ、NetlifyやFirebase Hostingにデプロイするだけでは、`example.com/show/[id]`でしか開くことができません。
そこで各プラットフォームに、`example.com/show/1`などのURLを叩いた時に、`/show/[id]/index.html`の内容を返すリライトの設定を行います。

例えばNetlifyでは、公開ディレクトリに次のような`_redirects`を用意します。

```_redirects
/show/:id /show/[id] 200
```

同じくFirebase hostingではfirebase.jsonにリライトの設定を追加します。

こういった設定を加えることで、データが増えた場合でも404を返さずにコンテンツを表示できます。
ただ、この対応だけでは動的にogpを返却することや、速度的なデメリット（1の方法ではHTML読み込み時点でコンテンツが表示されている）を背負うことになります。

---

特に2.の方法は今後SSRを使いたいけど、今はSSRを行わず静的ファイルとして返す暫定対応的な使い方になると思います。

覚えて置くと初期フェーズからNext.jsの採用を行え、将来SSRをする際に移行コストが小さくなるのでおすすめです。
【備忘録】SharePointのゲストユーザーを再招待するときの注意点

SharePointにはテナント外のユーザーを招待する機能がある。組織外のユーザーとのファイル共有に便利なので、使っている組織も結構あるんじゃないか、と思う。

Azure ADアカウントや、マイクロソフトアカウントだけでなく、[G Suiteアカウントも招待](https://qiita.com/hisssa0102/items/a74fd4114fd17a408d03)できたりする。


かなり便利に使える（組織によるけど）。で、ちょっと厄介なのが「一度招待して、プロジェクト終わったからSharePointのアクセス権削除したユーザー」の扱い。後日、同じアカウントを招待しようとしたときに引っかかってしまい再招待できないケースがある。

ちょうど引っかかってしまったので、対応を備忘録がてらまとめてみた。

#引っかかってしまった！

・SharePointサイトにゲストユーザー招待して、プロジェクト進行
・プロジェクト終わったし、対象のSharePointグループからユーザーを削除
・Azure Active Directryからもゲストユーザー削除

・別プロジェクトで再アサインになったので、再度そのゲストユーザーを招待
・あれ・・・招待してるのにアクセスできないぞ・・・。


#なんで？

サイトコレクションにユーザーが残っていると、再招待に失敗するらしい。

もともと招待していたサイトの、SharePointグループを開いてみる。
URLの最後は、「MembershipGroupID=」で数字が入ってる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/defd28a1-01d6-c225-9106-a45c652f7961.png)

この数字を、0にする。これで、サイトコレクションのユーザーすべてのグループ。
ここに残っていると、再招待に失敗する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/8aa262b0-143c-862f-9acd-1bbd4511b3d7.png)

複数のサイトコレクションにユーザーが残っている場合は、すべてのサイトコレクションから対象のユーザーを削除する必要あり。

#トラブルシュート

やることは、この３つ。
１、AzureADから削除。削除済みユーザーからも削除済みであることを確認する。
２、対象のサイトからユーザーを削除。
３、対象サイトのサイトコレクションすべてのユーザーを含むSharePointグループから削除

それから再度招待すればOK。


#回避方法

AzureADから削除せずにおけば、大丈夫（らしい）
でも、不要なアカウントを残しておくのはセキュリティ管理上望ましくないからきっちり削除するほうがベターかなぁ、と。


#まとめ

ゲストユーザーのアカウント管理をどのようにしているかは組織のポリシーによるけど、もしも引っかかったらこれで解決するかもしれません。
勉強ログ_day4_MySQL入門③(テーブル属性・レコード抽出）

# はじめに
非エンジニアの勉強ログ。
**超初心者プレイ**のため、内容は自分の勉強メモです。

### 今日のゴール
- MySQLとやらにもっと触ってみる

### 環境
- ホストOS：Windows10 Pro 1903
- [こちら](https://qiita.com/kantan/items/099e2c3ed700f1781df8)で構築した環境を利用する
- MySQL:5.7.27

### 参考資料・引用元など
- ドットインストール：[MySQL入門](https://dotinstall.com/lessons/basic_mysql_v3 "MySQL入門") ←勉強はこれを基軸に進める
- Qiita：[よく使うMySQLコマンド集](https://qiita.com/CyberMergina/items/f889519e6be19c46f5f4)

# テーブルの属性（情報）を変える
- 基本は**alter**
- add, drop, change　でフィールド属性（情報）を追加変更策個
- addではafterをあとにつけてフィールド追加位置指定可能

```ruby:mysql
alter table testtable01 add user_name varchar(255);
alter table testtable01 add person varchar(255) after user_name;
alter table testtable01 drop person;
alter table testtable01 change user_name varchar(80) default 'nobody';
```

テーブル自体の名前もあとからalterで変えられるよ

```ruby:mysql
alter table testtable01 rename users;
```

# レコードを条件つけて抽出する
 **where**を使います

```ruby:mysql
select * from users where age >= 20;
```
### 等号不等号

| 条件 | 書き方 |
|:-----|:-----|
| ～より多い | > ～ |
| ～より少ない | < ～ |
| ～以上 | >= ～ |
| ～以下 | <= ～ |
| ～と同じ | = ～ |
| ～と同じじゃない（～以外） | <> ～　または　!= ～ |
| nullだ | is null |
| nullじゃない | is not null |

### 記号以外（and, not, between, in）
andやnotもつかえるよ
betweenで代用したりも出来る

```ruby:mysql
select * from users where age >= 0 and age <= 19;
select * from users where age between 0 and 19;
```

等号（=）はinと代用できたりする

```ruby:mysql
select * from users where user_name = 'sato', or name = 'Mary';
select * from users where user_name in ('sato', 'Mary');
```
### 文字列検索

文字列検索も可能。
あいまい検索時は「%」（ワイルドカード）
大文字小文字区別したかったら「like binary」
文字数は「_」

```ruby:mysql
select * from users where user_name like 'sato';
select * from users where user_name like 's%';
select * from users where user_name like binary 'S%';
select * from users where user_name like '____';
```

### 並び替え
** order by ** をつかいます
降順にしたい場合は　descをあとにつける

```ruby:mysql
select * from users order by age desc;
```

### 絞り込み
上位3名、とか絞り込みたい場合は「limit」

```ruby:mysql
select * from users order by age desc limit 5;
```


# あとがき
- 業務でやりたいことには程遠いんだよな　もっとがんばる
- 今回はじめてMarkdownでtableを書いた　書きづらいな
リモートのpython3(psycopg2)からubuntu16.04@AWSのpostgresqlに接続

###前提
#####①ubuntu16.04をAWS上で立ち上げpython3,postgresqlをインストール完了
#####②python3でpsyopg2が扱える
以下はSelectクエリの実行例です。リモートで実行する前にローカルで問題なく実行できることを確認しておきます。

```python3
#################################
###    Selectクエリの実行例    ###
#################################
import psycopg2, psycopg2.extras

# 1. Postgesqlの接続設定(設定に合わせて修正してください)
#HOST     = "localhost  #ローカルで実行するとき
HOST     = "172.0.0.1"  
PORT     = "5432"
DBNAME   = "postgres"
USER     = "postgres"
PASSWORD = "p@ssword"
CREDENTIAL = "host={h} port={p} dbname={db} user={u} password={pa}"\
	.format(h=HOST,p=PORT,db=DBNAME,u=USER,pa=PASSWORD)

QUERY = "Select * from exercise" #テーブル名は任意に設定してください


# 2. Postgresに接続してクエリを実行
with psycopg2.connect(CREDENTIAL) as conn:
    with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur:
        
        # クエリ実行
        cur.execute(QUERY) 
        rows = cur.fetchall()

# 3. 結果を表示
print(rows[0])
```

###やったこと
#####①セキュリティグループの設定(下図の赤枠の設定)
![Postgresql_リモート.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139714/70adf202-0c91-0c47-cdb2-e3749026e774.jpeg)
※「0.0.0.0/0」はすべてのリモートアクセスを許可しているので注意してください。

セキュリティグループの設定をする前にリモート接続を実行すると以下の通りTimeoutエラーが出ました。

```python

OperationalError: could not connect to server: Connection timed out (0x0000274C/10060)
	Is the server running on host "【リモートIP】" and accepting
	TCP/IP connections on port 5432?
```
セキュリティグループの設定にPostgresqlを追加すると以下のRefusedエラーに代わりました。これでTCPの設定はOKです。

```python
OperationalError: could not connect to server: Connection refused (0x0000274D/10061)
	Is the server running on host "【リモートIP】" and accepting
	TCP/IP connections on port 5432?
```

#####②postgresqlの設定ファイルの修正とpostgresqlの再起動
ph_hba.conf と　postgresql.confのファイルを修正します。そして修正後にpostgesqlを再起動するのですが以下のブログの最後の方で詳しく説明されていますのでこちらを参考ください。
https://qiita.com/ibara1454/items/40ce2d82926f48cf02bc

##### 以上で終了です。ここまでの設定をすれば接続してクエリがリモートから実行できました。