OmniAICreator/Qiita-1.07M huggingface dataset:
【Java】組み合わせを実装してみた。

# 数学の組み合わせを Java で実装してみた

異なるn個の中から異なるr個とる組み合わせを Java で実装してみました。
r個の数だけループする実装は見たことがありますが、
r個が変わっても大丈夫なようにしたくていろいろ考えました。


# ソースコード

下記コードは 5個 の中から 3個 とるようになっています。

```Java
import java.util.ArrayList;
import java.util.List;

public class Trial {

    public static void main(String[] args) {
        Trial me = new Trial();
        me.exec(args);
    }

    public void exec(String[] args) {
        // 文字列の配列
        String[] strArray = new String[] { "a", "b", "c", "d", "e" };
        // 組み合わせを取得
        String[][] combinations = getCombinations(strArray, 3);
        // 結果出力
        for (String[] combination : combinations) {
            for (String str : combination) {
                System.out.print("  " + str);
            }
            System.out.println();
        }
    }

    private String[][] getCombinations(String[] strArray, int selectCount) {
        // 結果を詰める用のリスト
        List<String[]> list = new ArrayList<>();
        // ちょいちょい使うので変数に保持
        int len = strArray.length;
        // 配列の長さから２進数での最大値を求める。
        int dec = 0;
        for (int i = 0; i < len; i++) {
            dec += Math.pow(2, i);
        }
        // 最大値からデクリメントしていく。
        for (int num = dec; 0 < num; num--) {
            // ２進数表記の文字列にする。（０埋めはされない）
            String bin = Integer.toBinaryString(num);
            if (!isCombination(bin, selectCount)) {
                // 1 の数が選択数と一致しない場合は無視する。
                continue;
            }
            int j = bin.length() - 1;
            int tmplen = len - bin.length();
            String[] combination = new String[selectCount];
            int idx = selectCount - 1;
            for (int i = len - 1; tmplen <= i; i--) {
                if (bin.charAt(j--) == '1') {
                    combination[idx--] = strArray[i];
                }
            }
            list.add(combination);
        }
        return list.toArray(new String[0][0]);
    }

    private boolean isCombination(String str, int selectCount) {
        int sum = 0;
        for (int i = 0; i < str.length(); i++) {
            sum += Character.getNumericValue(str.charAt(i));
        }
        if (sum == selectCount) {
            return true;
        }
        return false;
    }
}
```

# 実行結果

```
  a  b  c
  a  b  d
  a  b  e
  a  c  d
  a  c  e
  a  d  e
  b  c  d
  b  c  e
  b  d  e
  c  d  e
```

5個から3個をとる組み合わせは、5! / (2! * (5 - 2)!) = 10
たぶん合ってる。


# 最後に

パフォーマンスや大きな数字を扱うことを考えると改善の余地は大いにあると思います。

以上
コメント機能（Ajax）実装

自分用にまとめます。

# 実装

**コントローラー・モデル作成済み**

```ruby:routes.erb
  resources :posts do
    resources :comments, only: [:create, :destroy]
  end
```

コメントはpostsのshowページで投稿や一覧表示、削除など行うため、createとdestroyのみ作成。
<br>


```ruby:comments_controller.rb
class CommentsController < ApplicationController

  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.new(comment_params)
    @comment.user_id = current_user.id
    @comments = @post.comments.all
    @comment.save
    render :create
  end

  def destroy
    @comment = Comment.find_by(id: params[:id], post_id: params[:post_id]).destroy
    @comment.destroy
    render :destroy
  end

  private
    def comment_params
      params.require(:comment).permit(:comment, :post_id)
    end
end
```
redirect_to などで遷移の記述部分を変更。
上記の場合、
**createアクションの際は、create.js.erb
destroyアクションの際は、destroy.js.erb**
に飛ぶようになっている。

js.erbは後ほど作成するファイル。
<br>


```ruby:posts_controller.rb
class PostsController < ApplicationController
  def show
    @post = Post.find(params[:id])
    @comment = Comment.new
    @comments = @post.comments.all
  end
end
```
今回はposts/showでコメントの投稿をできるようにする
<br>

```ruby:posts/show.html.slim
# コメント一覧表示
.row
  .col-lg-4
    .col-lg-4

      # create.js.erbで書き換えるため記述必須
      div id="comment-text"

        # コメント一覧部分をパーシャルで飛ばす
        = render 'comments/comment', comments: @comments

    
# コメントフォーム
  .row
    .col-lg-3
    .col-lg-6.text-center
      .frame-post-show

        # jsファイルを呼び出すためにlocal: trueの記述を外す
        = form_with(model: [@post, @comment]) do |f|

          = f.label :comment, class: "font-weight-bold col-lg-3 text-center"
          <br>
          = f.text_area :comment, :size=>"57x5"
          <br>

          .text-center= f.submit "コメントする", class: "btn btn-outline-secondary btn-sm"
```

<br>


_comment.html.slimファイルをcommentsディレクトリ配下に手動で作成
パーシャルで飛ばしたコメント一覧部分を貼り付ける。

```ruby:comments/_comment.html.slim
- @comments.each do |comment|

  # destroy.js.erbで書き換えるため記述必須
  div id="comment-#{comment.id}"
    .frame-post-comment
      = attachment_image_tag comment.user, :image, fallback: 'noimage.png', size: "50x40", class: "mb-3"
      = link_to comment.user.name, user_path(comment.user)
      - if comment.user == current_user
      
        # jsファイルを呼び出すためにremote: trueを追記
        = link_to '削除', post_comment_path(comment.post, comment), method: :delete, remote: true, data: { confirm: "削除してよろしいですか？" }, class: "btn btn-outline-danger btn-sm m-0 ml-3"
      <br>
      small.m-0= comment.created_at.to_s(:datetime_jp)
      .mt-4.mb-2= comment.comment
```

<br>


create.js.erbファイルをcommentsディレクトリ配下に手動で作成

```ruby:comments/create.js.erb

#　id="comment-text"部分を_comment.html.slimの内容にページ遷移なしで書き換える
$('#comment-text').html("<%= j(render 'comments/comment',{ comments: @comments }) %>");

# f.text_areaを空にする（記述しないと、投稿した後もフォームにコメント内容が残ったままになる）
$('textarea').val('');
```

<br>


destroy.js.erbファイルをcommentsディレクトリ配下に手動で作成

```ruby:comments/destroy.js.erb

# "comment-#{comment.id}"を持った投稿を非表示にする
$('#comment-<%= @comment.id %>').remove();
```


**完成！**
JavaはWord文書にハイパーリンクを追加します

通常、Word文書を編集するときに、特定のテキストまたは画像にハイパーリンクを挿入すると、ユーザーが他のターゲットの場所やWebページにすばやくジャンプできるようになります。今日の記事では、Free Spire.Doc for Javaを使用して、Word文書にテキストハイパーリンクと画像ハイパーリンクを追加する方法を紹介します。

**JARパッケージのインポート**
**方法1：**[Free Spire.Doc for Java](https://www.e-iceblue.com/Download/doc-for-java-free.html)をダウンロードして解凍し、libフォルダーのSpire.Doc.jarパッケージを依存関係としてJavaアプリケーションにインポートします。
**方法2：**Mavenリポジトリーを介してJARパッケージをインストールし、pom.xmlファイルを以下のように構成します

```java
<repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.doc.free</artifactId>
        <version>2.7.3</version>
    </dependency>
</dependencies>
```

**Javaコード**

```java
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.Section;
import com.spire.doc.documents.HorizontalAlignment;
import com.spire.doc.documents.HyperlinkType;
import com.spire.doc.documents.Paragraph;
import com.spire.doc.fields.DocPicture;

public class InsertHyperlinks {

    public static void main(String[] args) {

        //Word文書を作成する
        Document doc = new Document();
        Section section = doc.addSection();

        //Webリンクを挿入
        Paragraph paragraph = section.addParagraph();
        paragraph.appendText("ウェブリンク: ");
        paragraph.appendHyperlink("https://www.google.com/", "ホームページ", HyperlinkType.Web_Link);

        //メールリンクを挿入
        paragraph = section.addParagraph();
        paragraph.appendText("メールリンク: ");
        paragraph.appendHyperlink("mailto:xxx@outlook.com", "xxx@outlook.com", HyperlinkType.E_Mail_Link);

        //ファイルリンクを挿入する
        paragraph = section.addParagraph();
        paragraph.appendText("ファイルリンク: ");
        String filePath = "C:\\Users\\Administrator\\Desktop\\sample.pptx";
        paragraph.appendHyperlink(filePath, "クリックしてレポートを開く", HyperlinkType.File_Link);

        //画像ハイパーリンクを挿入
        paragraph = section.addParagraph();
        paragraph.appendText("画像ハイパーリンク: ");
        paragraph = section.addParagraph();
        DocPicture picture = paragraph.appendPicture("C:\\Users\\Administrator\\IdeaProjects\\Spire.Doc\\logo (2).jpg");
        paragraph.appendHyperlink("https://www.google.com/", picture, HyperlinkType.Web_Link);

        for (int i = 0; i < section.getParagraphs().getCount(); i++) {

            //段落を中央揃え
            section.getParagraphs().get(i).getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
            //段落の最後にスペースを自動的に追加する
            section.getParagraphs().get(i).getFormat().setAfterAutoSpacing(true);

            //ファイルに保存
            doc.saveToFile("InsertHyperlinks.docx", FileFormat.Docx_2013);
        }
    }
}
```

![link.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/1c3228ca-e618-e19b-e5ef-44a8f750ac7d.png)
storybookでPHPを利用してAPIデータを取得する


別ドメインのAPIデータを取得するような仕組みの場合、phpを使用して同ドメインのデータとして取得したい場合があると思います。
storybookでこれを実現する方法を紹介します。

## フォルダ構成
npxでインストールしたものとAPI用のphpフォルダを置いた状態で前提として進めます。

```
/.storybook
/stories
/php/
  /api/
    items.php
/package.json
```


## ローカル環境でPHPを使う場合
APIを取得するだけであればphpのビルドインサーバー使うのが楽だと思います。

    php -S 0.0.0.0:8000 -t ./php

0.0.0.0（localhost）


## storybookでproxyを使う方法

### 1. 【http-proxy-middleware】をインストールする

    npm i http-proxy-middleware -D

### 2. storybookのconfigに【middleware.js】を置く
configのフォルダ(デフォルトだと.storybook)下に【middleware.js】を置いて以下の様な記述をします。

【例】拡張子がphpになってるものをproxyするパターン

```js
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = router =>
  router.use(
    "**/*.php",
    createProxyMiddleware({
      target: "http://localhost:8000/",
    })
  );
```

【例】/api以下をproxyして、本番URLに合わせてリライトするパターン

```js
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = router =>
  router.use(
    "/api",
    createProxyMiddleware({
      target: "http://localhost:8000/",
      pathRewrite: {
        '^/api/items': '/api/items.php',
      },
    })
  );
```

ビルドインサーバーを実行した状態で、storybookの【 http://localhost:6006/api/items 】を叩くとproxyが動作していることを確認できます。


## 一つのコマンドで実行できるようにする

ビルドインサーバーとstorybook両方のコマンドを実行するのは面倒だと思うので、一つで実行できるようにします。

### 1. 【npm-run-all】をインストール

    npm i npm-run-all -D


### 2. package.jsonにコマンドを追加する

```json
  "scripts": {
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook",
    "proxy": "php -S 0.0.0.0:8000 -t php/",
    "start": "npm-run-all -p proxy storybook"
  }
```

storybook実行中にproxyのログが必要ない場合は、proxyのオプションに-qを付けると消せます。

## ローカルだけproxyを使いたい場合やパスを変えたい場合

storybookは、.storybookの中身を別のフォルダに用意することで、configを分けることが出来ます。
コマンドのオプション(-c)でフォルダを指定します

    start-storybook -c .storybook/dev
    build-storybook -c .storybook/build

このような形でconfigを分けると、dev専用の【middleware.js】を仕込むことができます。
CLIでS3のファイルをアップロードしよう

#はじめに
S3をマネジメントコンソール画面で作ることはできるが、CLIで操作して作成したことがないため、今回挑戦してみた。

#手順
<h2>AWS CLIの確認</h2>
AWS CLIがインストールされているか下記のコマンドで確認。

```
aws --version
```

<h2>S3の権限設定</h2>
IAM>ロール>権限を設定したいロールをクリック。
「ポリシーをアタッチします」ボタンを押す。
<img width="1279" alt="スクリーンショット 2020-08-03 16.00.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/e7291ed9-1e3a-6aa4-895a-9ed0f092a328.png">
ポリシーのフィルタでs3と入力し、「AmazonFullAccess」を選択。ポリシーのアタッチを押す。
<img width="1110" alt="スクリーンショット 2020-08-03 16.04.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/9c9ed32e-47a5-3e2a-75c6-1761d1f9311a.png">
アタッチされました、と表示される。
<img width="891" alt="スクリーンショット 2020-08-03 16.09.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/e3b5cb49-ab95-92b9-aa2b-c9f1a1db0509.png">

<h2>デフォルトリージョンを設定</h2>

```
$ aws configure
AWS Access Key ID [None]: 
AWS Secret Access Key [None]:
Default region name [None]: ap-northeast-1
Default output format [None]: json
```
「AWS Access Key ID [None]:」と「AWS Secret Access Key [None]:」には何も指定しない。

<h2>S3バケットを作成</h2>
```
$ aws mb s3://hoge　※hogeの部分は重複負荷なので、一意になるようにする。
$aws s3 ls ※バゲットが作成できたか確認。
```
マネジメントコンソールでも確認できる。

<h2>S3バケットにファイルをアップロード</h2>
インターネット上で任意の画像をアップロードする。
Chromeブラウザの場合は画像を右クリックして、「画像アドレスをコピー」を選択。
<img width="823" alt="スクリーンショット 2020-08-03 16.19.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/0d53bc80-ba2c-ccc7-2bb6-2718a09c45a4.png">
作業をするためのworkディレクトリをホームディレクトリに作成。
workディレクトリにwgetコマンドで画像アドレスを引数に指定して、ダウンロード。

```
$ mkdir ~/work
$ cd ~/work
$ wget https://hogehoge/hogehoge.png
```

s3 lsコマンドをバケットを指定して、実行。画像があるか確認する。

```
$ aws s3 ls s3://hoge
```

マネジメントコンソールでも画像があるか確認可能。

下記コマンドでCLIからパブリックなアクセス権限を設定。

```
$ aws s3api put-object-acl --acl public-read --bucket ファイル名 --key 画像名(hoge.png)
```

アクセスコントロールリストで許可設定があるか確認する。

```
$ aws s3api get-object-acl --bucket  ファイル名 --key 画像名(hoge.png)
```


マネジメントコンソールでオブジェクトURLをクリックして、画像が開けるか確認。
上記のような手順を踏むと、画像が表示される。

もしオブジェクトURLを押しても「AccessDenied」となって画像が表示されなかったら、該当オブジェクトの概要の「公開する」ボタンをおせば、表示される。
<img width="1049" alt="スクリーンショット 2020-08-03 19.59.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/eb76840b-21f6-c9ce-686c-127714d1e618.png">


参考
AWSではじめるLinux入門ガイド
Pandas で欠損値を含む整数型を扱う

従来、Pandas Series では欠損値を含む整数型は扱うことができなかった。

``` python
pd.Series([1, 2, None], dtype=int)
```

```
TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
```

型を明示せずに欠損値を含む数値データを読み込んだ際は float64 型にキャストされる。

``` python
pd.Series([1, 2, None])
```

```
0    1.0
1    2.0
2    NaN
dtype: float64
```

この振る舞いは「`numpy.nan` は float 型の値だから」という理由に起因するが、我々は欠損値が扱いたいのであって別に `numpy.nan` である必要はない。

これに対して Pandas v0.24.0 から [Nullable integer data type](https://pandas.pydata.org/pandas-docs/stable/user_guide/integer_na.html) が追加された。 `numpy.nan` の代わりに新たに `pandas.NA` を導入することでこの問題に対応したようだ。

``` python
pd.Series([1, 2, None], dtype=pd.Int64Dtype())
```

```
0       1
1       2
2    <NA>
dtype: Int64
```

dtype に指定する値は `pd.Int64Dtype()` の代わりに文字列 `"Int64"` でも同様に動く。(`I` が大文字である点に注意。)

また、ドキュメントに

> IntegerArray is currently experimental.

と書かれている通り、この機能はまだ実験段階なので利用する際は注意する必要がある。
Vue CLIのactive-classを使ってCSSを適用させる

#やりたいこと
![スクリーンショット 2020-08-03 16.00.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659936/aca7a579-1062-cb0f-38e6-d0863d3f0a0a.png)
![スクリーンショット 2020-08-03 16.00.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659936/21dde784-2e3a-2d4d-2dd8-4936ff89bd38.png)


現在表示しているページのアイコンだけ色を変える。
Vuetifyを使います。

#やり方
###active-class属性をつけ、cssを適用する。

```vue
<router-link active-class="link-active" :to="{name:'Fav'}"> //ハート
 <v-btn icon>
  <v-icon>mdi-heart</v-icon>
 </v-btn>
</router-link>

<router-link active-class="link-active" :to="{name: 'Search'}"> //検索 
 <v-btn icon>
  <v-icon>mdi-magnify</v-icon>
 </v-btn>
</router-link>
```

```vue
<style scoped>
a{
  text-decoration: none;
}
.link-active .v-btn--icon .v-icon{
  color: rgb(202, 96, 114);
}
</style>
```

`.v-btn--icon .v-icon`をつけることを忘れない。
#問題点
####選択されていないlinkにもcssが適用されてしまう。
![スクリーンショット 2020-08-03 15.54.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659936/e45c1371-7b66-3e01-00a0-f0b83e9e2ca2.png)

検索のページでは、ハートのアイコンは適用してほしくないが
URLが一致しているとそれ以降は全てactiveになってしまうため、ハートと検索のページのアイコンにcolorが適用されてしまう。

#解決策
####`exact`を追加
`active-class`属性に`exact`を追加することによってURLが完全に一致する時でないとactiveにならない。

#最終的なコード

```vue
<router-link active-class="link-active" exact  :to="{name:'Fav'}">
 <v-btn icon>
  <v-icon>mdi-heart</v-icon>
 </v-btn>
</router-link>

<router-link active-class="link-active" exact  :to="{name: 'Search'}">
 <v-btn icon>
  <v-icon>mdi-magnify</v-icon>
 </v-btn>
</router-link>
```
```vue
<style scoped>
a{
  text-decoration: none;
}
.link-active .v-btn--icon .v-icon{
  color: rgb(202, 96, 114);
}
</style>
```
JSのpush()について

JSのpush()について

初心者がJSのpush()についてメモしています。

#### push() メソッド
配列の末尾に 1 つ以上の要素を追加する
[参考](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/push)

```js
const animals = ['pigs', 'goats', 'sheep'];

const count = animals.push('cows');
console.log(count);
// expected output: 4
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows"]

animals.push('chickens', 'cats', 'dogs');
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]

```

 [参考「push」の返り値について](https://www.sejuku.net/blog/84475)

```js
var items = [1,2,3,4];
var result = items.push();
console.log(result);
```

- 連想配列では「push」を使えない
- 「push」はあくまで配列の組み込みメソッド
- 「push」を使って、配列の中に別の配列を追加するのは特に問題ない

```js
var obj = { name:'太郎', age:30 };
obj.push( ['花子', 28] );
console.log( obj );
```
実行結果

```js
Uncaught TypeError: obj.push is not a function
```

- 連想配列に要素を追加するには、まだ連想配列にないキー文字列を指定して値を代入します。疑似コードは以下

```js
arr[キー配列] = 値//keyとvalueをセットする
```


- しかし、配列の中にオブジェクトを追加することは可能
連想配列に配列を pushはだめ、
配列にオブジェクトを pushは OK

```js

var items = [1,2,3,4];
items.push({one:1,two:2,three:3});
console.log(items);
```

### 「pop」は配列の末尾のデータを削除する

```pop.js

var array = [1,2,3,4,5];
array.pop();
console.log(array);
```

```js
[1,2,3,4]
```


### concatメソッドで結合

```js

var array1 = ['aaa','bbb'];
var array2 = ['ccc','ddd'];
var result = array1.concat(array2);

console.log(result);
```
BibTeXのエントリ種別 (article, inproceedings etc...)

# はじめに
最近$\LaTeX$を書いていて、BibTeXの書き方でつまづいたのでその内容についてまとめます。
具体的には、Bibファイルの文献情報を手書きで修正したらなにも表示されないことがありました。
実行環境は[Overleaf](https://www.overleaf.com/)です。

# そもそもBibTexとは？
[こちら](https://qiita.com/SUZUKI_Masaya/items/14f9727845e020f8e7e9)の記事がわかりやすかったので共有します。

# 起きた問題と解決方法
ネット上で収集した論文の情報をもとに以下のようなBibTeXを書いたところ、学会名 (journal) が出力されませんでした。

```wrong.bib
@inproceedings{
    closedform,
    author = {Levin, Anat and Lischinski, Dani and Weiss, Yair},
    title = {A Closed Form Solution to Natural Image Matting},
    journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence},
    year = {2006},
    pages = {61–68},
}
```
理由は簡単で、 `@inproceedings`というエントリ種別が、`journal`という項目をサポートしていないためです。
`@inproceedings`や`@article`などの各エントリには書かなければいけない必須項目と、書いても良いオプション項目があります。
具体的には以下の通りです。
>`inproceedings`
必須項目： `author`, `title`, `booktitle`, `year`
オプション項目: `editor`, `pages`, `organization`, `publisher`, `address`, `month`, `note`, `key`

>`article`
必須項目: `author`, `title`, `journal`, `year`
オプション項目: `volume`, `number`, `pages`, `month`, `note`, `key`

（[Wikipedia](https://ja.wikipedia.org/wiki/BibTeX)を参考にしています）

これ以外の項目は、追加しても表示されないようです。ですので、さきほどの文献情報は以下のように書くと正しく出力されます。

```correct.bib
@inproceedings{
    closedform,
    author = {Levin, Anat and Lischinski, Dani and Weiss, Yair},
    title = {A Closed Form Solution to Natural Image Matting},
    booktitle = {IEEE Transactions on Pattern Analysis and Machine Intelligence},
    year = {2006},
    pages = {61–68},
}
```

# おまけ
記事の冒頭で書いた$\LaTeX$という文字を出力するのにちょっと苦労したので書き方を載せておきます。

```
$\LaTeX$
```

これは以下のリンクを参考にしました。
- [Qiitaの数式チートシート](https://qiita.com/PlanetMeron/items/63ac58898541cbe81ada)
- [LaTeXコマンド集](http://www.latex-cmd.com/special/special.html#logo)
OS自作環境をMacに作成する

Macのバイナリー形式よりもELFのほうがなにかと楽なのでクロスコンパイル環境を構築します。

## Dockerでクロスコンパイル環境をインストール

以下Dockerファイル
```Dockerfile
FROM ubuntu:latest
MAINTAINER username
WORKDIR /home/projects

RUN apt-get update && apt-get install -y \
  vim \
  gcc \
  g++ \
  binutils \
  build-essential

```

ビルド

```
docker run --rm -v $PWD:/home/projects 9665b0eb66db /bin/bash -c "cd /home/projects; make clean & make" |
```

## QEmuをインストール

コンパイルしたファイルを実行するための仮想環境を構築します。

```
brew install qemu
```

これで環境準備が出来ました。
Node.jsよりODBCでOracle, Salesforceなどに１ドライバで接続

#はじめに

Node.jsアプリケーションからODBCでSQL Server、Oracle、DB2、Postgres、MongoDBなどのDBや、Salesforce、Eloqua、Oracle Sales Cloud、Oracle Service CloudなどのSaaSアプリケーションに接続する必要性があるならば、DataDirect ODBCドライバを利用すると楽勝です。

この記事では、DataDirect ODBC ドライバを使用して Node.js から Oracle データベースに接続してみます。

#事前準備
Node.js

#DataDirect Oracle ODBC ドライバのダウンロード＆インストール

1,<a href="https://www.ashisuto.co.jp/datadirect/app_download/" target="_blank">ここ</a>からOracleデータベース用の64ビットODBCドライバをダウンロードします。

2,パッケージを展開し、インストーラーを実行してODBCドライバをインストールします。

3,ODBC Administrator（64ビット）を開き、新しいデータソースを追加するには、[追加]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662096/bc2bc029-4c6d-7713-df04-556e269dba31.png)


4,ドライバに「DataDirect 8.0 Oracle Wire Protocol」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662096/4baccf44-d74a-07b5-5a2a-8f46283bdbca.png)



5,ここで、ホスト名、ポート、SID/サービス名などの接続情報を入力し、Test Connectをクリックして接続の詳細を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662096/b394eee7-6101-55be-482f-6eea429502ad.png)


#Node.js ODBC パッケージのインストール

1,Node.jsでODBCドライバを使用するために、node-odbcパッケージをインストールします。

2,以下を実行し、パッケージをインストールします。

```console
npm i odbc
```

#Node.jsよりOralceに接続

1,以下はDataDirect ODBC ドライバを使用してOracle に接続し、テーブルにクエリを実行するサンプル コードです。

```console
var db = require('odbc')()
    , cn = "Dsn=Oracle;UID=saikrishnabobba;PWD=<password>;"
//open the connection
db.open(cn, function (err) {
    if (err) {
      return console.log(err);
    }
// Run a sample query
     db.query("select * from COUNTRIES", function (err, rows, moreResultSets) {
       
      if (err) {
        return console.log(err);
      }
       
      console.log(rows);
     });
  });
```

2,DSN、ユーザー名、パスワード、クエリを要件に応じて変更してください。上記のコードを実行すると、テーブルのデータをコンソールに出力します。


簡単ですね！
他のRBD、SaaS、NoSQLも手順は同様です。適切なデータソース用の DataDirect ODBC ドライバで、お好みのデータソースに接続できます。
Unity 3D入門 #12 [HQ Modular RE Mansionによる建物の建築&壁抜け,壁登り修正]

まず、HQ Modular RE Mansionのデモシーンの建築をゲームを作っていたシーンに挿入しましたが、建物があまりにも重すぎてUnityがフリーズしてしまいました。付属のプレハブを使って自分で建物を作ります。

壁を設置した際に片側からはしっかりと壁が見えるのに、反対側から壁が透けて見えてしまい、当たり判定もすけた側には存在しない事態に遭遇しました。

<img width="427" alt="スクリーンショット 2020-07-31 15.59.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670403/3320bc6b-7fa7-eaa4-40cb-33a796b6e25c.png">
見える側

<img width="345" alt="スクリーンショット 2020-07-31 16.00.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670403/7c2dd18b-b11b-42fa-bd8d-97481157d58e.png">
透ける側

これは、
<img width="961" alt="スクリーンショット 2020-07-31 16.02.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670403/35584200-98e4-cd25-4313-db44902d854c.png">
<img width="960" alt="スクリーンショット 2020-07-31 16.02.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670403/d6f107ec-e5ea-00d0-b9a6-822406ace67d.png">
このように同じ位置に180度回転させた同じ壁を配置することで解消しました。

>追記：上の画像ではxyz座標が全く同じ所にwallとwall(1)を配置しましたが、その場合見た目上二枚の壁の間に隙間ができてしまいましたので、wall(1)のz座標を変更することで二つが重なるようにしました。


また、プレイヤーが壁抜けをしてしまう不具合がありましたので、http://tsubakit1.hateblo.jp/entry/2016/07/09/235856 を参考にプレイヤーのRigidbodyのCollision DetectionをContinuosに変えることで解決しました。また、FixedTimeStepを0.02から0.01としました・

プレイヤーが一人称視点を上に向けたまま壁に向かって走ると壁を駆け上がってしまう不具合が生じました。
これは視点方向に向けてプレイヤーに特定の力を加えることで移動しているため、上方向に力が働いてしまったことが原因と考えられます。

```
float h = Input.GetAxis ("Horizontal");	// 入力デバイスの水平軸をhで定義
float v = Input.GetAxis ("Vertical");  // 入力デバイスの垂直軸をvで定義
if (Mathf.Max(Mathf.Abs(v), Mathf.Abs(h)) > 0.1) {
    velocity = new Vector3 (h, 0, v);  // キー入力から方向ベクトルを導出			
    velocity = cameraObject.transform.TransformDirection (velocity);  // キャラクターのローカル空間での方向に変換
    velocity = new Vector3 (velocity.x, 0, velocity.z);  //上下方向の力をゼロにする
    velocity *= forwardSpeed;  // 移動速度を掛ける
    transform.localPosition += velocity * Time.fixedDeltaTime;
}
```

このようにプレイヤーの移動において上下方向の力をゼロにします。
No template for interactive requestの対処法

アプリ作成中にNo template for interactive requestが発生した。


####エラー
私の場合は
No template for interactive request
PagesController#index is missing a template for request formats: text/html

であった。

```ruby:routes.rb
Rails.application.routes.draw do
  resources :pages
  root 'pages#index'
end
```

```ruby:pagescontroller
class PagesController < ApplicationController

  def index
  end
end
```

ビューファイルもしっかりapp/view/pagesにindex.html.hamlで作成していたので、原因がわからず解決できなかった。


####原因
PagesController#index is missing a template for request formats: text/htmlとエラー文ではhtml文を呼んでいたが、自分はhamlファイルを生成してしまっていた。

####解決法
ファイル名をindex.html.hamlからindex.html.erbに変更

これで解決する事ができた


####hamlでのビューファイルを呼び出すために
投稿者はhamlを利用したかったが、hamlを使うには haml-railsというgemをインストールしなければならなかったらしい。　

```ruby:gemfile
gem 'haml-rails'
```
これで、hamlファイルを呼び出す事ができた。



###反省
この解決だけで１時間ほど時間を食ってしまったのが辛かったので、もっと速い間隔で試行錯誤を行うことを心がける。
【Nginx】invalid number of arguments in "root" directive in /etc/nginx/conf.d/default.conf:の対処法

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/6f7a611b-57d9-c6c8-32e4-3493fe4909e0.png" width=600 />


Nginxにアクセス出来ない事案が発生し、ログを追ってみると`docker-compose up`直後に以下のエラーが出ていることに気が付きました。

```
invalid number of arguments in "root" directive in /etc/nginx/conf.d/default.conf:8
```

default.confの8行目がおかしいということは文面から読み取れます。


## 原因は文法エラー

```nginx.conf
server {
  listen 80;
  server_name localhost;

  root /var/www/html;
  index index.php index.html

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  location / {
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ \.php$ {
    fastcgi_pass php:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
  }
}
```

６行目の`index index.php index.html`末尾のセミコロンが抜けてた事が原因でした。
【MySQL】アクセス権限エラーで突如MySQLが起動できなくなった件

Amazon Linux2で「yum update」すると、突如MySQLが起動しなくなりました。

次のコマンドを実行。

```
$ systemctl start mysqld.service
```

次のエラーが発生。

```
Job for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details.
```
「systemctl status mysqld.service」や「journalctl -xe」を見てと書いてあるが見ても原因はわからず。。。
下記を実行してMySQLのログを確認。

```
$ less /var/log/mysqld.log
```

```:出力ログ
2020-08-03T03:41:05.785105Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2020-08-03T03:41:05.787080Z 0 [Note] /usr/sbin/mysqld (mysqld 5.7.31) starting as process 20768 ...
2020-08-03T03:41:05.791536Z 0 [Note] InnoDB: PUNCH HOLE support available
2020-08-03T03:41:05.791556Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2020-08-03T03:41:05.791560Z 0 [Note] InnoDB: Uses event mutexes
2020-08-03T03:41:05.791564Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2020-08-03T03:41:05.791568Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2020-08-03T03:41:05.791573Z 0 [Note] InnoDB: Using Linux native AIO
2020-08-03T03:41:05.791793Z 0 [Note] InnoDB: Number of pools: 1
2020-08-03T03:41:05.791873Z 0 [Note] InnoDB: Using CPU crc32 instructions
mysqld: Can't create/write to file '/tmp/ibbHa1X6' (Errcode: 13 - Permission denied)
2020-08-03T03:41:05.791916Z 0 [ERROR] InnoDB: Unable to create temporary file; errno: 13
2020-08-03T03:41:05.791922Z 0 [ERROR] InnoDB: Plugin initialization aborted with error Generic error
2020-08-03T03:41:05.791927Z 0 [ERROR] Plugin 'InnoDB' init function returned error.
2020-08-03T03:41:05.791930Z 0 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
2020-08-03T03:41:05.791933Z 0 [ERROR] Failed to initialize builtin plugins.
2020-08-03T03:41:05.791936Z 0 [ERROR] Aborting

2020-08-03T03:41:05.791970Z 0 [Note] Binlog end
2020-08-03T03:41:05.792017Z 0 [Note] Shutting down plugin 'CSV'
2020-08-03T03:41:05.792245Z 0 [Note] /usr/sbin/mysqld: Shutdown complete
```

「mysqld: Can't create/write to file '/tmp/ibbHa1X6' (Errcode: 13 - Permission denied)」
ここが原因でした。
翻訳すると、「アクセスが拒否されて、「/tmp/ibbHa1X6」にファイルを作成、書き込みができません。」と書かれています。
「/tmp」のアクセス権限を確認すると、所有者以外書き込みができないようになっていました。

```
drwxr-xr-x   8 root root  253 Aug  3 03:58 tmp
```

次のコマンドで権限を変更。

```
$ chmod 777 /tmp
```

```
drwxrwxrwx   8 root root  253 Aug  3 03:58 tmp
```

これで、無事MySQLにアクセスできるようになりました。
このエラーが発生した原因はわからないままです。（yum updateで「/tmp」の権限が変わったのか、「/tmp」を使うようになったのか・・・？）


今回は簡単な修正でしたが、MySQLのステータスやログを確認する機会が少なく、割と時間がかかったので記事に残しておきます。
Ubuntu 20.04 への zoom のインストール方法

Ubuntu 20.04 への zoom のインストール方法です。

ソフトのダウンロード

```bash
wget http://zoom.us/client/latest/zoom_amd64.deb
```

必要なライブラリーのインストール

```bash
sudo apt install libgl1-mesa-glx libegl1-mesa libxcb-xtest0
```

zoom のインストール

```bash
sudo dpkg -i zoom_amd64.deb
```

起動

```bash
zoom
```

起動時の画面
![zoom_start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/cf679809-3e8a-3566-7f5d-b50eceee076e.png)

Sign In を選ぶと
![zoom_signin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/5dea8726-7c32-d163-9606-b506c800745e.png)

Sign In すると
![zoom_aug03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/90a45ce0-2bc3-bacf-fc9b-3cd42a748c83.png)
JSの Promise

JSの Promise
Promise.prototype.then()
JS初心者が苦し紛れにメモを取っています。

[参考：Promise.prototype.then()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then)

- then() メソッドは Promise を返す。最大2つの引数、 Promise が成功した場合と失敗した場合のコールバック関数を取る。


```js
const promise1 = new Promise((resolve, reject) => {
  resolve('Success!');
});

promise1.then((value) => {
  console.log(value);
  // expected output: "Success!"
});

```
？よくわからない、、


[参考2:JavaScript の Promise: 概要](https://developers.google.com/web/fundamentals/primers/promises?hl=ja)
- JavaScript はシングル スレッド
- JavaScript はペイント、スタイルの更新、ユーザー操作の処理（テキストのハイライト表示やフォーム コントロールの操作など）と同じキューに入っています。 これらいずれかの処理のアクティビティが、他のアクティビティを遅延させる

[参考3 JavaScriptのPromiseとjQueryのPromise](https://qiita.com/fakefurcoronet/items/cb2d2eba1a2e39f6643d)

#### 今のところの理解

- 順番通りに実行させたいときに使うもの
- 昔は順番通りに実行させたいときにコールバックなどでなんとか解決されていたが、ES6から公式になったもの
- 少し疲れたので、また気力があるときに理解を進める
ElixirでTCPのサーバーとクライアントを試しに作成

# はじめに
[Task and gen_tcp](https://elixir-lang.org/getting-started/mix-otp/task-and-gen-tcp.html)を読みながらやっても、TCPサーバーがうまく反応してくれなかったのですが、一応反応してくれたので残しておきます。

## TCPサーバー

```elixir
defmodule Tcp1 do
  @moduledoc """
  Tcp1 keeps the contexts that define your domain
  and business logic.

  Contexts are also responsible for managing your data, regardless
  if it comes from the database, an external API or others.
  """
  require Logger

  def accept(port) do
    {:ok, socket} = :gen_tcp.listen(port, [:binary, packet: 0, active: false, reuseaddr: true])
    Logger.info("Accepting connections on port #{port}")
    loop_acceptor(socket)
  end

  defp loop_acceptor(socket) do
    {:ok, client} = :gen_tcp.accept(socket)
    Logger.info("Connected")
    serve(client)
    loop_acceptor(socket)
  end

  defp serve(socket) do
    socket
    |> read()
    |> write(socket)

    serve(socket)
  end

  defp read(socket) do
    {:ok, data} = :gen_tcp.recv(socket, 0)
    Logger.info(data)
    data
  end

  defp write(line, socket) do
    :ok = :gen_tcp.send(socket, line)
  end
end
```

この行に変更を加えてあります。↓

```elixir
{:ok, socket} = :gen_tcp.listen(port, [:binary, packet: 0, active: false, reuseaddr: true])
```

もともとは`packet: :line`と書いてあったのですが、そのままだと動きませんでした。
クライアントから送られてくるデータが１行ずつ送信されてくるとかではなく、生のデータとして送信されているからのようです。
なので、`packet: 0`もしくは`packet: :raw`というふうに変更したら動きました。
※Line-Basedなプロトコル(\rとか\nで区切られてるようなやつ)を扱うときはちゃんと`:line`と指定してあげないとだめなようです。

## TCPクライアント
```elixir
defmodule Tcp2 do
  @moduledoc """
  Tcp2 keeps the contexts that define your domain
  and business logic.

  Contexts are also responsible for managing your data, regardless
  if it comes from the database, an external API or others.
  """

  require Logger

  @msg "msg from me"

  def connect() do
    {:ok, socket} = :gen_tcp.connect('localhost', 4040, [:binary, active: false])
    send_messages(socket)
  end

  defp send_messages(socket) do
    :timer.sleep(1000)
    :ok = :gen_tcp.send(socket, @msg)
    Logger.info(@msg)
    {:ok, _data} = :gen_tcp.recv(socket, 0)
    send_messages(socket)
  end
end
```
1秒経つごとに、"msg from me"というデータを接続先のサーバーに送信してくれます。

# さいごに
とりあえず試しに動くようなものができました。
`:line`とか`:raw`とかそのへんはまた実装していく上で調べながら注意していこうと思います。

# 参考リンク
> https://elixirforum.com/t/i-can-connect-using-gen-tcp-but-i-cant-send-receive-data-what-is-wrong-with-this-implementation/6487/4
> https://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/design/line_based.html
laravel 画像アップロードとリサイズ

laravelでの画像アップロードとリサイズについてまとめていきたいと思います。

こちらで[画像アップロード機能](https://qiita.com/yuki_911/items/a698c6db40aed5f4cc5a)の説明を行っています。よかったら見てください。


```Post.Controller.php
    public function store(PostRequest $request)
    {
        $post = new Post;

        //ファイルが存在しているか
        if($request->hasFile('path')){
            $file = $request->file('path');//ファイルを取得
            $filename = $file->getClientOriginalName();//ファイル名取得
            Image::make($file)
                ->resize(300, 300)
                ->save(public_path( 'storage/post_image/' . $filename ));
            $post->path = $filename;
        }
        $post->save();

        return redirect('/post')->with('success', '投稿しました！');
    }
```

`$file = $request->file('path');`
でformからのファイルを取得してファイル名を
 `            $filename = $file->getClientOriginalName();`
で取得。

`Image::make($file)
->resize(300, 300)
->save(public_path( 'storage/post_image/' . $filename ))`
リサイズしたいファイルを渡し、サイズ指定し、保存。
**public_path**では画像を読み込む必要があるので、**storage/〇〇**としてください

**保存:storage/app/public
読込:public/storage**

``
【GCP】BeyondCorp Remote Accessを実装してみた

リモートワークが盛り上がってきておりますが、VPNの代替としてGoogleが提唱しているBeyondCorp Remote Access。
結局どんなサービスなの？何を実装すればGoogleの言う、ゼロトラストは実現するの？っていうところなんですが、正直、まだ答えは出ていません。

一番明確にしないといけないのは、「GKE ingressを使って何が違うのか？」ってこと。
Googleとしては、GKE ingressを使うこと推奨しているのですが、HTTPSロードバランサと何が違うの？ってのがわからない。。

GKE ingressを「使ったとき」「使わなかったとき」両方試したので、簡単にまとめました。
今後また内容を修正する可能性はあります。


#GKE ingressを利用しなかった時の設定
1.お名前.comにて、検証用のドメインを取得。
2.GCE上にインスタンスを作成し、テスト用アプリケーションを構築する。
3.作成したインスタンスを非マネージドインスタンスグループに登録する。
4.Cloud LoadBalancingをHTTPS負荷分散で作成。
　バックエンドを作成した非マネージドインスタンスグループにする。
　フロントエンドをHTTPSとし、マネージドSSHを利用し、テストドメインを登録する。
　固定IPを取得し、フロントエンドのドメインとIPをひもづける
5.DNSサーバのAレコードに取得した固定IPをひもづける
6.Oauthに同意する。
7.ACMに特定のIPのみ許可する設定を入れる。
8.IAPを設定し、許可したいアカウントをユーザに登録し、アクセスレベルに設定したACMのルールを適用する。

#GKE ingressを利用したときの設定
1.お名前.comにて、検証用のドメインを取得。
2.GCE上にインスタンスを作成し、テスト用アプリケーションを構築する。
3.作成したインスタンスを非マネージドインスタンスグループに登録する。
4.GKEのクラスタを作成。
5.Serviceとingressにて、種類がノードポートのものをチェックし、ingressを作成する。
　項目はすべてデフォルト
6.Cloud LoadBalancingが作成されていることを確認。
7.Cloud LoadBalancingにて以下を設定。
　バックエンドを作成した非マネージドインスタンスグループにする。
　フロントエンドをHTTPSとし、マネージドSSHを利用し、テストドメインを登録する。
　固定IPを取得し、フロントエンドのドメインとIPをひもづける
8.DNSサーバのAレコードに取得した固定IPをひもづける
9.Oauthに同意する。
10.ACMに特定のIPのみ許可する設定を入れる。
11.IAPを設定し、許可したいアカウントをユーザに登録し、アクセスレベルに設定したACMのルールを適用する。

コンテナに疎いので、GKEingressについても、かなり調べました。
L7ロードバランサに鳴るということなのですが、HTTPSロードバランサでもOKなのでは？と思ってしまうんですよね。
このへんは、もう少し調べます。
Slack APIでメッセージ削除

# はじめに

他の方の作られたSlack APPで作ったAPI Tokenを使ってBotの開発していたところ、会社のgeneralチャネルに大量にメッセージを投稿してしまい、対処に焦ったのでcurlを使った削除手順を残します。

自分の作成したSlack APPが投稿したメッセージはUI上から自分で削除できるのですが、他の方の作られたSlack APPが投稿したメッセージはUI上から削除することができない（多分）ので、Slack APIを使って削除する必要があります。

# メッセージ削除APIについて
メッセージ削除のAPIはSlack APIの公式ドキュメントに記載してあります。
https://api.slack.com/methods/chat.delete

削除に必要な情報は削除対象のメッセージが投稿されているchannelとts（timestamp）の2つ（＋メッセージを誤爆したToken）。

```
{
  "channel": "PARENT_CHANNEL_ID",
  "ts": "MESSAGE_TO_DELETE"
}
```

特定のメッセージのtsはどこから参照できるかドキュメントからでは読み取れない。。
手順で説明します。

# 手順

１．channel id, tsを取得  
削除したいメッセージのメニューから「Copy link」をクリックして、URLをクリップボードにコピーする。
下記のURLがコピーされます。

```
https://xxxxxx.slack.com/archives/<channel id>/<ts>
```


- `channel id` はそのままリクエストの値に設定
- `ts`はSlack API上のtsの形式に書き換える
  - 先頭の `p` を削除
  - 末尾6桁のところで `.`で区切る

```:例
p1596432722002300　→　1596432722.002300 (これをAPIのリクエストに使用する）
```




２．curlコマンドを叩く

```
curl -XPOST "https://slack.com/api/chat.delete?token=<token>&channel=<channel id>&ts=<ts>" 
```

成功すると以下のようなレスポンスが返ってきます。

```
{"ok":true,"channel":"<channel id>","ts":"<ts>"}
```

以上です。

# 最後に
メッセージ削除APIの情報自体はすぐに見つけられましたが、tsを変換する方法が分からず削除するまで結構時間を要してしまいました。参考リンクに感謝です。

# 参考リンク
[Slack API | メッセージのURLからメッセージ内容を取得する](https://qiita.com/YumaInaura/items/e46bf2ae6a222648b01f)
Eclipseにプラグインをインストールする

前回の記事はこちらです。
[eclipseにGradleとSpringを追加する](https://qiita.com/kty000/items/f2f8cf3e48e01fcc3956)

今回はプラグインを追加しましょう。
なにかありましたらご指摘いただけますと嬉しいです。

#プラグインってなに？
当たり前にプラグインという言葉を見ますが超初心者からすれば「いやプラグインインストールってなんやねん」ってなりますよね（私がそうです）
プラグインとはもっといろんなことができるような拡張機能のソフトウェアのことです。
タイトルはEclipseをもっと使いやすくいろいろできるようにする機能機能を追加しましょうという意味ですね。




#インストールする
実際にプラグインをインストールしましょう。今回は

・Eclipse Java EE Developer Tools
・Eclipse Java Web Developer Tools
・Eclipse Web Developer Tools
・JST Server Adapters
・JST Server Adapters Extensions

を追加します。

１．[help] => [Install New Software]から入ります。
２．-- All vailable Sites --に変更し、Eclipse Java EEと入力すると画像のようになりますので、チェックが入っていることを確認して[next]![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550109/cd78f146-9691-0f7e-a5a3-551b42d27e20.png)
３．特にいじらず[next]を押下で大丈夫です。ライセンスの確認をされたらI acceptを選択して[finish]
４．インストールをしばらく待ち、Eclipseを再起動したら完了です。

１～４の手順ですべてインストールして完了です。

この作業中は急にフリーズしたりして大丈夫か、、となりましたがあせらず待ちましょう。私も初めはえ！？となっていろいろポチポチしてしまいました。

次はspringのプロジェクトを作ってみましょう。
次 => [spring + gradle でhelloworldを表示してみる](https://qiita.com/kty000/items/ca08f627f9bacecfa34e)
なぜ、ログイン実装後に Register で 「Oops VFS connection does not exist」と表示されるのか

#なぜ、ログイン実装後に Register で 「Oops VFS connection does not exist」と表示されるのか
このエラーの背景としては、
私は、Laravel で Auth 機能を用いてログイン機能を実装するところでした。
問題なく 「web.php 」と「Routing」と「Controller」はしっかり書けていました。

しかし、
https://gyazo.com/bdf3f4c82bc15c334adb050a5723b634
このように表示される模様。

エラー内容は 

「Oops VFS connection does not exist」

ふむ。
直訳すると

「おっとっと VFS接続が存在しません」

おっとっとじゃないわw　泣きたいわw
多分、接続サーバー先の問題とかそう言った類の問題な気がすると思いました。
なぜなら、

その証拠に、ログインしないで実際に他の階層に降りようとすると、
Auth の設定で Login の画面に強制転送さられるからです。

この事件に陥る人が他にもいるのではと思い、
ネットで探していたところ、似たような方はいました。

その対処法としては、AWS の問題であるから、インスタンスを停止して、再度起動である。
しかし、何度やってもダメでした。
仕方なく私のメンターさんに相談したところ、解決策がありました。

#解決策
それは Laravelの中にある TrustProxies.php の設定を変更することでした。
PATH：/プロジェクト名/app/Http/Middleware/TrustProxies.php

```php

<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var array|string
     */
    protected $proxies;

    /**
     * The headers that should be used to detect proxies.
     *
     * @var int
     */
    protected $headers = Request::HEADER_X_FORWARDED_ALL;
}


```

TrustProxies.phpのコードはこのようになっております。
変更点は以下の通りです。

```php

/**
     * The trusted proxies for this application.
     *
     * @var array|string
     */
    protected $proxies = "**";
```

ワイルドカードの "**" を $proxies に設定してあげることでした。
メンターさんになぜこうなるか聞いてみました。
 ”**” を付けてあげないと Http で通信している状態になってしまうからだそうです。 
つまり "**" を付けてあげることで Https を許可していることになるそうです。

これで表示されるか
やってみました！！

表示されました！！
https://gyazo.com/104db9302114aa52ea579752a3afc41e

メンターさんすごい。。

最後に変更後のコードを記載しておきます。

```php
<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var array|string
     */
    protected $proxies = "**";

    /**
     * The headers that should be used to detect proxies.
     *
     * @var int
     */
    protected $headers = Request::HEADER_X_FORWARDED_ALL;
}
```

これは忘れずに覚えておきます。
今日も積み上げたぜ٩( ᐛ )و
KVMメモ

先代から引き継いだサーバにKVMで運用しているサーバがあって、Try&Errorしたのでメモ。
環境はホストはRHEL7.3、ゲストはCentOS7.4とWindowsServer2012


# よく使うコマンド一覧
- 一覧表示

```
virsh list --all
```
- 起動/終了

```
virsh start <guestname>
virsh shutdown <guestname>
```
- 設定ファイル編集

```
virsh edit <guestname>
```

# VM複製
+ 複製対象のゲストは落としておく

```
virsh shutdown <guestname>
```
+ ディスクImgは大体この辺に置くと思う。たぶん。

```
mkdir /opt/kvm/images/xxxxxx
cd /opt/kvm/images/xxxxxx
```
+ 複製実施

```
# virt-clone --original <コピー元ゲスト名> --name <コピー先ゲスト名> --file /opt/kvm/images/xxxxxx/<imgfilepath>
virt-clone --original Template_CentOS7 --name guest_CentOS7 --file /opt/kvm/images/xxxxxx/guest_CentOS7.img
```
+ 起動

```
virsh start <コピー先ゲスト名>
```

# ディスク追加

+ ディスク追加対象のゲストは落としておく

```
virsh shutdown <guestname>
```

+ ディスクImgは大体この辺に置くと思う。たぶん。

```
mkdir /opt/kvm/images/xxxxxx
cd /opt/kvm/images/xxxxxx
```
+ ディスクイメージ作成（以下は50Gで切った感じ）

```
qemu-img create dev-guest-xxx.img 50G
```

+ ゲストVMの設定ファイルにディスク追加用の定義を追記(念のためバックアップとっておくとよいよ)

```
virsh edit <ゲスト名>

    #以下追加
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw' cache='none'/>
      <source file='/opt/kvm/images/xxxxxx/dev-guest-xxx.img'/>
      <target dev='hdb' bus='ide'/>　　　# devはデバイス名、Windowsとかだとhda、hdb、hdc・・・となるのでいい感じに変える
    </disk>
```

+ ゲスト起動（設定ファイルにミスがある場合はここで起動失敗する)

```
virsh start <guestname>
```

+ その後ゲストOS側で普通にフォーマットする。

# ディスク拡張

+ ディスク追加対象のゲストは落としておく（念のため）

```
virsh shutdown <guestname>
```

+ ディスクImgの状況を確認

```
qemu-img info dev-guest-xxx.img
```

+ ディスクImgをバックアップ

```
cp dev-guest-xxx.img /tmp
```

+ ディスクイメージ拡張（以下は+50Gしたイメージ）

```
qemu-img resize dev-guest-xxx.img +50G
```
+ ディスクImgの状況を確認

```
qemu-img info dev-guest-xxx.img
```

+ ゲスト起動

```
virsh start <guestname>
```

+ その後ゲストOS側でディスク状況を確認してみてね。
【リーダーシップ】リーダーシッププロの５つの共通点

# リーダーシッププロの5つの共通点
- 価値と原則を明確にする。
    - メンバーがチームの価値を明確に理解できればできるほど成果が出る。
    - リーダ一人で思っている価値をメンバーに強要しない。
    - 毎日、目的がある質問をする。
    
- ビージョンでわくわくさせる。
    - 具体的で明確な未来を提示する。
    - メンバーが未来の中で自分の役割を見つけるようにする。
      - メンバーがどのアスピレーションとビージョンを持っているのかそのメンバーの役割を見つけるようにする。
- 新しいことにチャレンジする。
    - 外部現実に敏感に感じる。
    - 洞察力を得るために頑張る。
      - あなたに挫折感を与える人たちの観点を受け入れ、学べるところを探す探す。
      - 観点を変えようとせず、その人の話をそのまま聞いてみる。
      - 枠から離れて交流がすくない少ない人々に様々な意見を聞く。
      
- 自ら行動できるようにする。
    - 権限を与え、メンバー自分がリーダだと感じさせる。
    
- メンバーの熱情が生み出されるようにする。
    - メンバーの能力を最高に引き出す。
    - 確信の言動を使う。
エラー「ERROR: The Compose file './docker-compose.yml' is invalid because:」の対処法

```
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.php.volumes contains an invalid type, it should be an array
```
`docker-compose up`した時に上記のようなエラーが出た場合の対処法です。

## 原因はYaml文法エラー

エラー内容の`services.php.volumes`の部分の文法が不正ということです。

### Before : 不正な文法

```(不正文法)docker-compose.yml
version: '3'
services:
  nginx:
    image: nginx:latest
    ports:
      - 8080:80
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./wwww/html:/var/www/html
    depends_on:
      - php
  php:
    build: ./php
    volumes:
      -./www/html:/var/www/html
```

### After : 正しい文法

```(正しい文法)docker-compose.yml
version: '3'
services:
  nginx:
    image: nginx:latest
    ports:
      - 8080:80
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./wwww/html:/var/www/html
    depends_on:
      - php
  php:
    build: ./php
    volumes:
      - ./www/html:/var/www/html
```

具体的には以下の部分です。

**Before : 不正な文法**

```yaml
-./www/html:/var/www/html
```

**After : 正しい文法**

```yaml
- ./www/html:/var/www/html
```


Yamlの文法は`-(ハイフン)`の後ろには必ず半角スペースが必要です。
うっかり見落としていました。
ターミナルでコマンドを実行した際にOperation not permitted が表示された場合の対処法

#####[rails中級チュートリアルアプリ作成](https://techracho.bpsinc.jp/hachi8833/2018_02_06/51401)
の最中にトップページへのルーティング、コントローラー作成をし、rails sを実行しようとしたところ、

```ruby:ターミナル
Operation not permitted 
```
と、エラー文が表示されてしまった。


####解決法
システム環境設定→セキュリティとプライバシー→プライバシー→左に並んでいる中からフルディスクアクセスを選択→ターミナルにチェックを入れる。


これでターミナルを再起動すると解決する事ができた。


####参考サイト
https://gori.me/mac/mac-tips/112082
IBM Cloudの利用を始めるときに何はともあれやるべきこと その2

IBM Cloudを使い始めるときに最初にやっておくべきこと　その2です（その1は[こちら](https://qiita.com/hisato_imanishi/items/d14f229cc07cf9a26b6d)）。

今回は、IBM Cloudで利用料金が一定額以上発生した場合にメールで通知が届くようにする設定です。

この設定をしておけば、不正利用があった場合や、自分が作成したサービスを削除するのを忘れて課金が発生した場合に早期に気づくことができ、課金のダメージを軽減することができます。

なお、IBM Cloudのアカウントの種別は、「ライト・アカウント」、「従量課金アカウント」、「サブスクリプション・アカウント」の3種類がありますが、これらのうち「ライト・アカウント」は課金のためのクレジットカードを登録しておらず、したがって課金も発生しないため、当ページに記載の設定は不要です（設定できません）。

以下が設定の手順です。

IBM Cloudにログイン後、画面右上の「管理」→「請求および使用量」を選択します。
<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/d41f0f81-cef8-e347-e78b-d405b3f37925.png">

画面左側のメニューの「消費量の通知」を選択します。
<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/688542ea-0456-5747-cfbf-ac28365598dc.png">

「事前通知の設定」の「合計アカウント消費量」の「有効化」をオンに設定します。
これにより、月額の使用料金が「しきい値」の80%, 90%, 100%を超えたそれぞれのタイミングで、「受信者」のメールアドレスに通知が来るようになります(個人情報のため黒塗りしています)。
<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/6e312650-4539-a787-6199-0e3605ab23e9.png">

「しきい値」を変更したり、「受信者」を追加したい場合は、上記画面の右側の赤枠部分(縦の三点リーダ）をクリックし、「編集」を選択します。

表示されたダイアログで、受信するメールアドレスを追加したり、しきい値の金額を変更することができます。
<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/1409f818-d927-694c-c632-c48fab3806b8.png">



なお、**クラシック・インフラストラクチャーのサーバの料金については通知の対象外**となります。そのため、通知の設定有無にかかわらず、毎月の利用料金のチェックは欠かさず実施することをおすすめします。
（クラシック・インフラストラクチャーも対象になればと思うのですが...）
[失敗談] ndarray に + 1 したら、意図せず dtype が変わってしまった

# 前提

拙作の強化学習用ライブラリ[cpprb](https://gitlab.com/ymd_h/cpprb)の開発の中で遭遇したバグ ([issue](https://gitlab.com/ymd_h/cpprb/-/issues/112))

強化学習のExperience Replay用にデータを一時保存しておくためのライブラリであり、そのデータの型はユーザーがコンストラクタで指定し、内部では[Numpyのndarray](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html)として保存していた。

# バグ (失敗)

先日、（厳密には違うが）こんな感じのコードで ndarray に加算を行ったところ、意図せず dtype まで変わってしまい挙動がおかしくなってしまった。

```python:バグ
import numpy as np

def create_buffer(shape,dtype):
    return np.zeros(shape=shape,dtype=dtype) + 1

create_buffer(1,np.bool) # array([1]) np.bool ではなくなってる!! np.int64
```

オペレータ `+` の代わりに、[numpy.add](https://numpy.org/doc/stable/reference/generated/numpy.add.html) を利用しても出力される型は変わってしまう。
(仮に出力先 `out` に一旦格納した元の変数を指定すると`numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'add' output from dtype('int64') to dtype('bool') with casting rule 'same_kind'` と怒られる。)

# 解決策

以下のように、計算した結果を要素毎に代入すると（あくまで型が変換可能な場合のみだが）元の型を維持した計算ができる。

```python:修正
import numpy as np

def create_buffer(shape,dtype):
    a = np.zeros(shape=shape,dtype=dtype)
    a[:] = a + 1
    return a

create_buffer(1,np.bool) # array([True])
```


# 余談

[別の目的](https://gitlab.com/ymd_h/cpprb/-/issues/105)があって、たまたま加算を実行しただけであって、加算自体には意味はない。
(boolの加算が...ということは、この記事の本題ではない。)

あくまで、ndarray にオブジェクトレベルの演算をしたら、意図せず型を変換されてしまったという失敗談。
【アルゴリズム】桁の足し算

# 問題説明
自然数Nを受け取って、Nの各桁の足し算を行いreturnするsolutionメソッドを作成してください。
**例）N=123の場合、1 + 2 + 3 = 6をreturn。**

# 条件
- Nの範囲：100,000,000以下の自然数

# 入出力の例
| N      |       answer |
|:-----------------|------------------:|
| 123|              6|
| 987|            24|

# 解説
※解説は私が作成したコードなので、もっといいアルゴリズム等々ありましたら、共有してください！

```java

public class Solution {
    public int solution(int n) {
        // 合計を保存用
        int sum = 0;
        while(n > 0) {
            sum += n % 10; // 10で割り算して余りを足していく。
            n /= 10;  // 10で割り算した結果を次の計算に使うためnに代入。
        }

        return sum;
    }
}
```
FilebeatでPostgreSQLのログをElasticsearchへ送る

# はじめに

FilebeatにはPostgreSQLログ用のモジュールが最初から同梱されており、モジュールを有効にするだけで利用できます。


# 環境

使用した環境は以下のとおり。

- CentOS 7.5
- Elasticsearch 7.8
- Kibana 7.8
- Filebeat 7.8

「[ElasticStack 7.8 環境構築](https://qiita.com/mkyz08/items/d4eb9f20efbd9dc77547)」で構築した環境を利用しています。


# Filebeatの設定

PostgreSQLログ用のモジュールを有効にします。

```
# filebeat modules enable postgresql
```

PostgreSQLログ用のモジュールの設定ファイルは以下のファイルです。
※先ほどのコマンドでpostgresql.yml.disabledからpostgresql.ymlに変更されているようです。

- /etc/filebeat/modules.d/postgresql.yml

ファイルは以下のようにPostgreSQLログのパスを環境に合わせて修正します。

```
- module: postgresql
  log:
    enabled: true
    var.paths: ["/data/log/postgresql-*.log"]

```

次にKibanaへ対してサンプルダッシュボードを作成するため、以下のように"setup.dashboards.enabled"を"true"に設定します。
他にElasticsearchへアウトプットするように設定しています。
※修正箇所のみ抜粋

```yml:filebeat.yml
# vi /etc/filebeat/filebeat.yml

setup.dashboards.enabled: true

output.elasticsearch:
  hosts: ["localhost:9200"]
```

他にもsetupコマンドでKibanaへ対してサンプルダッシュボードを作成することができます。

```
# filebeat setup
```

Kibanaには次のサンプルダッシュボードが生成されます。それ以外のモジュール用のダッシュボードも生成されています。

- [Filebeat PostgreSQL] Overview ECS

他にもPostgreSQL用にはQuery Durations等が表示できる、[Filebeat PostgreSQL] Query Duration Overview ECSというダッシュボードもありました。

最後にFilebeatを実行します。

```
# systemctl start filebeat
```


# Kibanaでの可視化

KibanaでPostgreSQLログ用のダッシュボードを選択すると以下のように表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179607/f249a7e8-a081-fb19-ebdd-c706095ff484.png)


# 参考

- [Quick start: modules for common log formats](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-modules-quickstart.html)
- [PostgreSQL module](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-postgresql.html)
ウェブサイト作成用備忘録・２号：background-image の疑似アニメーション制御その２

日々の学習のアウトプットの為、自主学習の際に工夫した内容を記録していきます。

今回は background-image プロパティの疑似アニメーション制御について

background-image プロパティは transition プロパティや animation プロパティ等のアニメーション制御には対応していません。

そこで、自分なりに試行錯誤することで、疑似的なアニメーション制御に成功したので、その方法などを記録していきます。

###方法２：JavaScript の動的制御で２種類の background-image の opacity を同時に操作することで、疑似的なクロスフェードを実装する。

####記述例

HTML

```
<html>
  <body>
    <div id="background1" class=""></div>
    <div id="background2" class="none"></div>
    <button id="change_screen" class="" type="button">背景変更</button>
  </body>
</html>
```

CSS

```
body {
  margin: 0;
}
#background1,
#background2 {
  min-height: 100%;
  min-width: 100%;
  opacity: 1;
  position: fixed;
  transition: all 1s;
  -webkit-transition: all 1s;
}
#background1 {
  background-image: url(背景画像１)
}
#background2 {
  background-image: url(背景画像２)
}
#background1.none,
#background2.none {
  opacity: 0;
}
#change_screen {
  position: relative;
}
```

javascript

```
jQuery(document).ready(function(){

  $("#change_screen").click(function(){
    $("#background1").toggleClass("none");
    $("#background2").toggleClass("none");
  });

});
```

####解説

１・背景画像の表示専用の空の div タグを二種類を用意する。

２・予め片方の div タグにはクラス none を設定し、透過処理の初期設定を行う。

３・背景変更ボタンをクリックすると、toggleClass メソッドでそれぞれの div タグの none クラスが切り替わる。

４・それぞれの div タグの透明度が逆転し、transition プロパティによって、１秒間の間にそれぞれの背景がアニメーションすることで、結果的にクロスフェードする。

今回はこれで以上になります。

あくまで自分用の備忘録ですが、他の方の参考になれば幸いです。