OmniAICreator/Qiita-1.07M huggingface dataset:
カスタムmixタスクからgothを使うと怒られる問題

ElixirにはRubyのRakeのようなツールとしてmixが提供されています。
mixもRakeのようにカスタムタスクを定義できるのですが一部のライブラリを使ったときGenServerのプロセスが起動されておらずエラーになったのでその対策を書きます。

## GenServerが動いてない

今回は適当なファイル `lib/mix/tasks/oath.ex`に `goth`の認証コードを書いたということで話を進めます。

```elixir
defmodule Mix.Tasks.Oath do
  use Mix.Task

  @shortdoc "認証実験"
  def run(_) do
    {:ok, token} = Goth.Token.for_scope("https://www.googleapis.com/auth/cloud-platform.read-only")
    IO.inspect GoogleApi.BigQuery.V2.Connection.new(token.token)
  end
end
```

これを実行するとこんなエラーが出ます(´；ω；｀)

```shell

> mix oath
Compiling 4 files (.ex)
Generated HOGE app
** (exit) exited in: GenServer.call(Goth.TokenStore, {:find, {:default, "https://www.googleapis.com/auth/cloud-platform.read-only", nil}}, 5000)
    ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
    (elixir 1.10.4) lib/gen_server.ex:1013: GenServer.call/3
    lib/goth/token.ex:71: Goth.Token.for_scope/2
    lib/mix/tasks/oath.ex:6: Mix.Tasks.Oath.run/1
    (mix 1.10.4) lib/mix/task.ex:330: Mix.Task.run_task/3
    (mix 1.10.4) lib/mix/cli.ex:82: Mix.CLI.run_task/2
```

mix.exsの `def application`に `:goth`を書いてみても同じエラーが出てしまいます...


## 解決策
関数の最初に `Application.ensure_all_started(:goth)`を書くとエラーが出なくなる

```elixir

def run(_) do
  Application.ensure_all_started(:goth)
  # ~~~~~~~~~~~~~~~

```


```elixir

> mix oath
Compiling 1 file (.ex)
%Tesla.Client{
  adapter: nil,
  fun: nil,
  post: [],
  pre: [
    {Tesla.Middleware.Headers, :call,
     [
       [
         {"authorization",
          "Bearer ~~~~~
       ]
     ]}
  ]
}
```
xargsさくっと使う

Bash

# ファイル検索

```bash
find /path/ -name "*php" -type f | xargs grep "hogehoge"
```

- コマンド置換

```bash
grep "hogehoge" $(find /path/ -name "*php" -type f)
```

※拡張子は指定する方が便利

# ファイル削除
```bash
find /path/ -name "hugahuga" -type f | xargs rm
```

※該当ファイルがなくてもエラーにならない

- コマンド置換

```bash
rm $(find /path/ -name "hugahuga" -type f)
```

# dockerコンテナ一括削除

```bash
docker ps -q | xargs docker stop
docker ps -qa | xargs docker rm
```

- コマンド置換

```bash
docker stop $(docker ps -q)
docker rm $(docker ps -qa)
```

# gitのbranch一括削除

```bash
git checkout master
git branch | grep -v "master" | xargs git branch -D
```

- コマンド置換

```bash
git checkout master
git branch -D $(git branch | grep -v "master")
```
vscodeコンテナー環境でgo rename出来ない

# 実行環境
VSCode 1.47.3
Go 1.14.4
Remote-Containers v0.128.0
# 問題
「シンボルの名前を変更 F2」を行ったら、

```
Rename failed: gorename: can't find package containing /****/****/***.go
名前の変更を実行できませんでした。
```
# 解決
1. ```ctrl + ,```設定ページ開く
1. 「go server」で検索する
1. 一番下に```Go:Use Language Serve```をチェックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198260/f035a615-4f3a-3eda-a8d3-ac8aefc8be09.png)
jsonに変換不要。Create MLのObject DetectionにIBM Cloud Annotationsをつかう

#Create MLのデータ形式をサポート
物体検出（Object Detection）用の注釈ツールは色々とありますが、
**Create MLでMLObject Detectorをトレーニングするなら、IBM Cloud Annotationsが便利**です。

**Create ML対応のデータ形式（json）で直接出力できる**からです。


<blockquote class="twitter-tweet"><p lang="en" dir="ltr">IBM Cloud Annotations Tool eases the process of AI data labeling <a href="https://t.co/KLdwmiyeoa">https://t.co/KLdwmiyeoa</a> <a href="https://t.co/ItlVG8oPhx">pic.twitter.com/ItlVG8oPhx</a></p>&mdash; DevOps.com (@devopsdotcom) <a href="https://twitter.com/devopsdotcom/status/1222938223166590978?ref_src=twsrc%5Etfw">January 30, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



他のツールでは、xml、txt、csvからjsonに変換する作業が必要になります。
（Create ML対応json形式例↓）

```json:annotations.json
[{"image":"pets0.jpg","annotations":[{"label":"cat","coordinates":{"x":348,"y":380,"width":113,"height":74}},{"label":"dog","coordinates":{"x":589,"y":390,"width":122,"height":75}}]},{"image":"pets1.jpg","annotations":[{"label":"cat","coordinates":{"x":233,"y":670,"width":238,"height":169}},
```
#無料で簡単に使える
１、ドラッグで境界ボックスをつける。
2、「File」から「**Export As Create ML**」を選ぶ。
これで画像とjsonのフォルダが保存され、**そのままCreate ML Object Detection のデータとして参照できます。**

#Tips
iPhoneのフルサイズでとった写真は、そのままアップロードすると時間がかかるので、サイズを小さくしてからアップすると速いです（どうせフルサイズでMLObjectDetectorにかけるわけではない。299 * 299ぐらいあればいい）。

機械学習関連の情報を発信しています。
MLBoysだいすけ　https://twitter.com/JackdeS11
MLBoysゆうじ https://twitter.com/oka_yuuji

Core MLやCreate ML、Visionを使ったアプリを作っています。
rockyshikoku@gmail.com

Looks Good To Me(わるくないね）おねがいします。
　　　　　　　　　　　　↓
php用のgRPCソースを生成するDockerfile

gRPCのプラグインをbrew等で入れることができなかったので、Dockerコマンド化しました.

# ディレクトリ構成
```
├── Dockerfile
├── protos/
│   └── sample.proto
└── gen/
```

* protos: protoファイルを置いておくディレクトリ
* gen: 生成されたコードが配置されるディレクトリ

# Dockerfile
```Dockerfile
FROM php:7.2.32-cli

WORKDIR /tmp
RUN apt-get update -y && apt-get install -y wget zip git automake zlib1g-dev libtool

# install protoc command
# releases: https://github.com/protocolbuffers/protobuf/releases
ENV proto_version 3.12.3
RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v${proto_version}/protoc-${proto_version}-linux-x86_64.zip \
    && unzip -d protoc protoc-${proto_version}-linux-x86_64.zip \
    && mv protoc/bin/* /usr/local/bin/ \
    && mv protoc/include/* /usr/local/include/

# install grpc php plugin
# releases: https://github.com/grpc/grpc/releases
ENV grpc_version v1.30.2
WORKDIR /var/local
RUN git clone -b ${grpc_version} https://github.com/grpc/grpc --depth=1
WORKDIR /var/local/grpc
RUN git submodule update --init \
    && make grpc_php_plugin \
    && cp -p ./bins/opt/grpc_php_plugin /usr/local/bin/

WORKDIR /var/local
RUN mkdir protos \
    && mkdir gen

ENTRYPOINT ["protoc", "--proto_path=/var/local/protos", "--php_out=/var/local/gen", "--grpc_out=/var/local/gen", "--plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin"]
CMD ["hello.proto"]

```

# コード生成コマンド
1. コンテナの中にボリュームマウントでprotoファイルを埋め込む
2. コンテナ内でソースが生成される
3. コンテナ内に生成されたファイルをボリュームマウントでローカルにコピーする

の流れです。

```
$ docker build -t grpc-php-gen -f docker/grpc-php-gen/Dockerfile .
$ docker run --rm -v $(PWD)/protos:/var/local/protos -v $(PWD)/gen:/var/local/gen grpc-php-gen sample.proto
```
letを使用することで、通るはずのテストが通らないFalse Alarmを生じる可能性がある

先日RSpecのテストコードにレビューを頂いたので、

なるべく多くを学びたいと思い、その内容を咀嚼する過程での気付きを書きたいと思います

元記事
[RSpecのEmail一意性テストで"Email has already been taken"問題と回避策 - Qiita](https://qiita.com/daddy_hacker/items/c84ae1b65831d5f7264d)

- なるべく小さいscope?（contextの中など）を見ただけでテストの内容が把握できるような書き方のほうが、読み手に理解しやすい、想定外の挙動を防ぐことができる。

- `let`を使って書くことはこれを実現するために有効

- `let`の遅延評価によって、テストによっては必要のないインスタンス変数を毎回`before`で定義するような冗長性を回避できる

  

が、この遅延評価を理解せずに、なんとなく変数代入の感覚で使用していたために以下のようなエラーに遭遇しました

# `let`を使用することで、通るはずのテストが通らないfalse Alarmを生じる可能性がある



## `let`と`let!`の使い分けが重要になりそうなケース

- テストを実施する時点と、前提となる条件の間に時間的なずれがある場合
- すでに完了しているものと、現在の比較が必要な場合
- モデルのテストの場合なら、一意性のテスト

## 遅延評価されるletが、実際にテストの失敗を招いたケース

レビューの内容を参考に、
属性の一意性についてのテストを書いてみた。

User modelの属性`username`の一意性についてのテストを以下のうように書くと

```ruby
    describe "username" do
      ...
      context "usernameが重複している場合" do
        let(:existing_user) { FactoryBot.create(:user, username: "alice") }
        subject { FactoryBot.build(:user, username: "alice" ) }
        it { is_expected.to be_invalid }
      end
      ...
    end
```



モデルで`username`属性についてのvalidationが記述されているにもかかわらず

```ruby
class User < ApplicationRecord
  validates :username, presence: true, uniqueness: true, length: { maximum: 12 }
  ...
end
```



validationがinvalidにならない

```
1) User#create username usernameが重複している場合 is expected to be invalid
     Failure/Error: it { is_expected.to be_invalid }
       expected `#<User id: nil, email: "test_user_5@example.com", created_at: nil, updated_at: nil, username: "alice">.invalid?` to return true, got false
```



テストの記述を変更する
（実際にレビューコードではこの書き方を提示してくれていました）
`let` >> `let!`

```ruby
    describe "username" do
      ...
      context "usernameが重複している場合" do
        let!(:existing_user) { FactoryBot.create(:user, username: "alice") } #let!に変更
        subject { FactoryBot.build(:user, username: "alice" ) }
        it { is_expected.to be_invalid }
      end
      ...
    end
```

このようにすると、想定通りテストがパスするようになる。

## `let`と`let!`の違い

- letは、itやexampleが実行されるまで評価されない
- let!は即座に実行される

`it { is_expected.to be_invalid }`の時点で、`existing_user`は存在完了していないといけない
英文でいうところ`let`は現在完了的な振る舞いをして、`let!`は過去完了の状態をつくってくれると考えると個人的にはしっくりきた。



# 参考

[RSpecのletを使うのはどんなときか？（翻訳） - Qiita](https://qiita.com/jnchito/items/cdd9eef2ed193267c651)

[使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」 - Qiita](https://qiita.com/jnchito/items/42193d066bd61c740612#%E9%81%85%E5%BB%B6%E8%A9%95%E4%BE%A1%E3%81%95%E3%82%8C%E3%82%8B-let-%E3%81%A8%E4%BA%8B%E5%89%8D%E3%81%AB%E5%AE%9F%E8%A1%8C%E3%81%95%E3%82%8C%E3%82%8B-let)
Datepickerで選択した日にちを、Riot.js側に渡したい

# やりたいこと
Datepickerで選択した日にちを、Riot.js側に渡したい

## 困ったこと
- onchangeとかoninputはイベント発火しない
- onblurではイベント発火したが、DatepickerのonSelectやonCloseより前となってしまい、選択後の日にちを取得できない
    - メモ：`datepicker onblur`で検索すると、そこそこ出てくる。

## 要点
- DatepickerのonSelect/onCloseで入力フォームのtriggerを発生させれば良い
    - でも、jQueryのtriggerはうまく発動しない(何故だろう・・・)
- Pure JavaScriptのdispatchEventならうまく動いた
    - カスタムイベントにしといた

# バージョン
- Riot.js：3.3.2
- jQuery：3.1.1
- Datepicker：1.10.4

# 実装
## Datepicker側(.jsファイルに書く方)
```
function doOpenCalendar () {
  $('#targetdate').datepicker({
    onSelect: function (dateText) {
      $('#targetdate').val(dateText)
    },
    onClose: function () {
      const event = new Event('myevent')
      document.getElementById(id).dispatchEvent(event)
    }
  })
  $('#targetdate').datepicker('show')
}
```

## Riot.js側(.tagファイルに書く方)
```
  <input
    id="targetdate"
    type="text"
    name="targetdate"
    readonly="readonly"
    onfocus={open_calendar}
    onmyevent={close_calendar}
  >

  open_calendar(e) {
    e.preventDefault()
    doOpenCalendar()
  }

  close_calendar(e) {
    e.preventDefault()
    console.log(e.target.value)
  }
```
リモートワークでも仕事が捗るチームの取り組み

新型コロナウイルスの影響でリモートワーク中心の働き方に変わりました。通勤時間や満員電車のストレスから解放され恩恵を受ける一方、オフィス勤務のように気軽に仕事の質問・相談ができずスピード感が下がったり、常に家で作業をしているので孤独に感じたり、働く上でいくつか支障がありました。そこでその支障を解消するためにチームで取り組んでいることを紹介します。


*エンジニア向けの記事です。

### 顔出し推奨でビデオ会議の朝会

リモートワーク下でもチーム内でコミュニケーションを取るために、ビデオ通話（顔出し推奨）で15分程度の朝会を毎日しております。朝会の内容は各メンバーのタスクの進捗・連絡事項・お悩みの共有が主です。また、顔出し推奨なのがポイントで、**チームの顔が見れることでテキストのコミュニケーションでは伝わらない安心感**を得ることができます。


### Discordを使ってオフィスのような会話を実現

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185492/f09d8dea-6c00-7c37-9d27-9740e291c9ba.png)


https://discord.com/new

Discordとはボイスチャットツールです。作成された部屋に入るとその部屋にいるユーザー間で会話（基本は音声のみ）できます。また、PCの画面共有の機能もあるので、画面を見ながらの会話もできます。

リモートワークの問題として、オフィス勤務のように仕事の質問や相談があったときに気軽に話しかけれない点があります。以下のように**部屋をダブルクリックすると部屋に入り、会話を始められ、気軽に質問や相談**ができます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185492/95007a35-14b4-267f-d9ef-b72a6e9fb362.png)

チームのルールでは、自分の部屋を作成して**話しかけられてもよいときに自分の部屋にいる**ようにしています。こうすることで、問題が起きた時に気軽に他のメンバーに質問・相談できます。


### 話した内容はテキストとしてまとめて共有

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185492/8bebf2f4-d234-a722-68d2-6890c29e6312.png)


こちらはリモートワークに限った話ではないと思いますが、
会議やDiscordで話した内容はテキストとしてまとめて共有するようにしています。（SlackやGithubでの共有が多いです）

こうすることで以下のメリットが生まれました。
・参加していない人も内容を知ることができる
・Slackの検索で引っかかる
・テキストとして記録に残すことで言語化の練習になる。



### Slackに実装メモのスレッドを立てる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185492/a1bc89cc-809b-a471-c625-36a95c0351d0.png)

Slackに実装メモのスレッドを立てると他の人の参考になったり、軌道修正が必要であれば正してくれるので嬉しい。



### Vscode Live Shareでペアプログラミング

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185492/bd870f7b-eb9a-2221-ed5a-228f74856418.png)
https://visualstudio.microsoft.com/ja/services/live-share/


VscodeのLive Share機能を使うとペアプロでナビゲーターでもエディタにコードを書くことができます。例えば、ナビゲーターがドライバーに対してより良い書き方のコードを教える場合にエディタに直接プログラムを書いて教えられるので便利です。

詳しくはこちらをご覧ください。
[DiscordとVSCodeを使ってリモートワークで快適にペアプロをする話](https://techblog.zozo.com/entry/remote-pairprogramming)




### 最後に

以上がリモートワークの支障を軽減させるための取り組みです。
ぜひ他に良かった取り組みがありましたら教えてくださると嬉しいです！
yarn workspace していなかったモノレポ で workspace 化

モノレポってとりあえず複数のパッケージをひとつのリポジトリで管理すればいいと思っていた
yarn workspace が便利なので移行した


## Before

直下に packages ディレクトリがあり、packages 下に各パッケージを置いているだけの状態
各パッケージで yarn install しているため、yarn.lock がそれぞれに存在する

```md
- /
  - /packages
    - /package-aaa
      - package.json
      - yarn.lock
      - ...
    - /package-bbb
      - package.json
      - yarn.lock
      - ...
    - /package-ccc
      - package.json
      - yarn.lock
      - ...
  - ...
```


## ルートに package.json 作成

```json:/package.json
{
  "name": "hoge",
  "private": true,
  "workspaces": [
    "packages/**"
  ],
  "...": "...ほか必要な項目は追加"
}
```


## yarn.lock を集める

そのまま yarn instal してしまうと、新たな依存関係を作ってしまう
現在の依存関係を引き継ぐため、ルートに yarn.lock を作成し、各 yarn.lock の内容を集める

```yaml:/yarn.lock
# /packages/package-aaa/yarn.lock の内容をコピペ
# /packages/package-bbb/yarn.lock の内容をコピペ
# /packages/package-ccc/yarn.lock の内容をコピペ
```

適当にコピペしているだけだが、あとで勝手に整理されるので安心する
コピペが完了したら各パッケージの yarn.lock は削除してよい (もう使わない)


## 各パッケージの package.json の必須項目の存在を確認する

name, version は必須 (他にも必須のものがあるかもしれない)
ないとあとでおかしくなるので確認

```json:/packages/package-aaa/packages.json
{
  "name": "@hoge/package-aaa",
  "version": "0.1.0",
  "...": "...ほかの項目はそのまま"
}
```

```json:/packages/package-bbb/packages.json
{
  "name": "@hoge/package-bbb",
  "version": "0.1.0",
  "...": "...ほかの項目はそのまま"
}
```

```json:/packages/package-ccc/packages.json
{
  "name": "@hoge/package-ccc",
  "version": "0.1.0",
  "...": "...ほかの項目はそのまま"
}
```


## yarn install

多分大丈夫なので yarn install

```sh
yarn install
```


## After

おわり

```md
- /
  - /packages
    - /package-aaa
      - package.json
      - ...
    - /package-bbb
      - package.json
      - ...
    - /package-ccc
      - package.json
      - ...
  - package.json
  - yarn.lock
  - ...
```
【Angular】値によってCSSを切り替える

書き方は二通り。
>①ngClassを使う
>②クラスバインディングを使う

```html
<!-- ngClass -->
<p [ngClass]="{ 'font-on': fontFlag }">ngClass</p>
<!-- クラスバインディング -->
<p [class.font-on]="fontFlag">css works!</p>

<button (click)="changeClass()">色を変える</button>
```
```css
p {
  color: black;
}
.font-on {
  color: red;
}
```
```typescript
export class CssComponent implements OnInit {
  fontFlag = false;
  constructor() {}

  ngOnInit() {}

  changeClass() {
    this.fontFlag = !this.fontFlag;
  }
}
```
![スクリーンショット 2020-07-28 13.50.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607742/6ceb3c69-2dd7-2803-792b-7179e37f988c.png)
ボタンを押すと色が変わります
![スクリーンショット 2020-07-28 13.50.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607742/12d16b1f-31e2-f308-c55e-148f9cca28d1.png)

単純に2種類を切り替えたいだけならクラスバインディング、
複数種類使い分けたいときはngClassが便利そう
lwc关联笔记(2) LMS解说

Lightning Message Service

需要注意的是，lms本身在vf里面可用，vf publish----vf subscribe
在aura里面也可用    aura publish-------aura subscribe

即是说，这三者可交互使用lms


Lms在lwc中应用解说

lms是在lwc，lc，vf这三方进行通信的时候使用的。

其本质是使用publish-subscribe的通信机制。


1.首先，我们需要创建一个SampleMessageChannel.meta的文件。路径是force-app/main/default的底下

```
<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <isExposed>true</isExposed>
    <lightningMessageFields>
        <fieldName>传递的字段名</fieldName>
    </lightningMessageFields>
    <lightningMessageFields>
        <fieldName>传递的字段名</fieldName>
    </lightningMessageFields>
    <masterLabel>信息频道名称</masterLabel>
</LightningMessageChannel>
```



2.为了能够往频道里注入信息，我们先要构建一个publish方


~~~
import { LightningElement,track  } from 'lwc';
import { publish,createMessageContext,releaseMessageContext } from 'lightning/messageService';
import SAMPLEMC from "@salesforce/messageChannel/SampleMessageChannel__c";
export default class MyPublisherComponent extends LightningElement {
    
    //重新创建一个新的context对象
    context = createMessageContext();
     
    publishMC() {
      //用数组的方式赋值，这里面的字段名需要和LightningMessageChannel里面的一致
        const message = {
            recordId: "some string",
            recordData: { value: "some value" }
        };
       //publish即可
        publish(this.context, SAMPLEMC, message);
    }
     
    disconnectedCallback() {
        releaseMessageContext(this.context);
    }
}













~~~


3.关于接收方，我们分开讨论

①如果是vf的情况

~~~

<script>
    // 引入channel的信息，书写方式为!$MessageChannel.+你设置的名字
    var SAMPLEMC = "{!$MessageChannel.SampleMessageChannel__c}";
    var subscriptionToMC;

    // 页面加载时就会自动调用，去取出你出版的值
    subscribeMC();

    // 方法的详细内容
    function subscribeMC() {
        //底下的操作是表示，当你没有取出出版值得时候才会执行
        if (!subscriptionToMC) {
            subscriptionToMC = sforce.one.subscribe(SAMPLEMC, onMCPublished);
        }
    }


    function onMCPublished(message) {
        //按照字段名去取出相应的值
        var recordId = message['recordId'];
        //按照新的值去重新加载页面
        pagererender(recordId);
    }

</script>


~~~



②lc的情况



lc的cmp文件里

~~~
按照如下的操作去导入lms，这是先决条件


<lightning:messageChannel type="SampleMessageChannel__c" aura:id="sampleMessageChannel" onMessage="{!c.handleReceiveMessage}"/>
~~~




lc的js里

~~~


     handleReceiveMessage: function (component, event, helper) {
        console.log('handleReceiveMessage');
        if (event != null) {
//从event.getParams();里得到结果
            var message = event.getParams();
//只需要message['recordId']来输出结果就好
            component.set("v.recordId", message['recordId']);
//刷新
            helper.refresh(component,event,helper);
        }
     }

~~~
受動的攻撃と同一オリジンポリシー

この記事は以下の書籍を参考にして執筆しました。

- [体系的に学ぶ 安全なWebアプリケーションの作り方 第2版［リフロー版］　脆弱性が生まれる原理と対策の実践](https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88%EF%BC%BB%E3%83%AA%E3%83%95%E3%83%AD%E3%83%BC%E7%89%88%EF%BC%BD-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8-%E6%B5%A9-ebook/dp/B07HHT54YR/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6%E3%81%82%E3%81%B7%E3%82%8A&qid=1595990262&s=digital-text&sr=1-2)

#ブラウザ側のセキュリティ
##サンドボックス

サンドボックスの中ではプログラムができることが制限されいる。

- ローカルファイルへのアクセス禁止
- プリンタなどの資源の利用禁止(画面表示は可能)
- ネットワークアクセスの制限(同一オリジンポリシー)

##同一オリジンポリシー
サイトをまたがったアクセスを禁止する

XMLHttpRequestでは相手の許可があれば同一オリジンでなくても通信できるCORSという規格が策定された。

##アプリケーション脆弱性と受動的攻撃
###XSS
iframeの外側のjavascriptで内側をアクセスすると同一オリジンポリシー違反だが
何らかの方法でiframeの内側にjavascriptを送り込んで実行させたらどうか

内側ならポリシー違反にならないため、アクセスができる。
これがクロス・サイトスクリプティング(XSS)

#参考文献
- [体系的に学ぶ 安全なWebアプリケーションの作り方 第2版［リフロー版］　脆弱性が生まれる原理と対策の実践](https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88%EF%BC%BB%E3%83%AA%E3%83%95%E3%83%AD%E3%83%BC%E7%89%88%EF%BC%BD-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8-%E6%B5%A9-ebook/dp/B07HHT54YR/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6%E3%81%82%E3%81%B7%E3%82%8A&qid=1595990262&s=digital-text&sr=1-2)
Deno: CouchDB のデータを削除 (Delete)

```ts:couch_delete.ts
// ---------------------------------------------------------------
//	couch_delete.ts
//
//					Jul/28/2020
//
// ---------------------------------------------------------------
import ky from 'https://deno.land/x/ky/index.js'
// ---------------------------------------------------------------
console.error ("*** 開始 ***")
const key_in:string = Deno.args[0]
console.log(key_in)

const url = "http://localhost:5984/nagano/" + key_in

const parsed = await ky.get(url).json()

console.log(parsed._rev)
console.log(parsed.name)

const url_del = url + '?rev=' + parsed._rev

const result = await ky.delete(url_del).json()

console.log(result)

console.error ("*** 終了 ***")
// ---------------------------------------------------------------
```

実行

```bash
deno run --allow-net couch_delete.ts t2027
```
HonKitのdockerイメージを作りました (日本語検索、日本語PDF出力に対応)

## dockerイメージの使い方

* https://hub.docker.com/repository/docker/tukiyo3/honkit
* https://github.com/tukiyo/docker-honkit

```yaml:docker-compose.yml
web:
  image: tukiyo3/honkit
  restart: always
  volumes:
    - ./honkit:/srv/honkit
  ports:
    - "4000:4000"
```

```sh:起動
docker-compose up
```

* http://localhost:4000

```sh
chmod -R 777 ./honkit/
# プラグインの設定
cp book.json ./honkit/

vim ./honkit/README.md
```

### Gitbookのプラグイン追加方法

* 日本語検索対応の`search-pro-fixed`を利用するには

```sh
npm i gitbook-plugin-search-pro-fixed
```

※ `gitbook install`ではないので注意！

```json:./honkit/book.json
{
    "plugins": [ "-lunr", "-search", "search-pro-fixed" ]
}
```

※ `search-pro-kui`ではうまく検索できなかった。


## GitHub Pages に UPするときのハマりポイント

* `_book` のような、アンダースコアから始まるフォルダは`404`を返される。
    * `.nojekyll`という空ファイルを置けば解決。

## HonKitについて

* mdbook より良い点
    * デザインが洗練されている。
    * IE11で動く。
* [GitBookをForkしてHonKitを作りました | Web Scratch](https://efcl.info/2020/06/19/githon/)
* Gitbook の更新が止まって `npm 6` までしか対応してなかったのをフォークしてして最新の`npm 14`に対応。
* https://github.com/honkit/honkit
* 開発が活発 [honkit/CHANGELOG.md](https://github.com/honkit/honkit/blob/master/CHANGELOG.md) 2020/7/28時点での最新は `3.5.2`

----

## (参考までに) 公式のdockerイメージの使い方

### honkit init

```yaml:docker-compose.yml
honkit:
  image: honkit/honkit
  restart: always
  volumes:
    - ./honkit:/srv/honkit
  ports:
    - 4000:4000
  working_dir: /srv/honkit
```

```sh
# init
docker-compose run honkit  honkit init
```

### honkit serve

```sh
# serve
docker-compose run honkit  honkit serve
```

もしくは以下

```yaml:docker-compose.yml
honkit:
  image: honkit/honkit
  restart: always
  volumes:
    - ./honkit:/srv/honkit
  ports:
    - 4000:4000
  working_dir: /srv/honkit
  command: honkit serve
```

```sh
docker-compose up
```

* http://localhost:4000
Deno: CouchDB のデータを更新 (Update)

```ts:couch_update.ts
// ---------------------------------------------------------------
//	couch_update.ts
//
//					Jul/28/2020
//
// ---------------------------------------------------------------
import ky from 'https://deno.land/x/ky/index.js'
// ---------------------------------------------------------------
function get_current_date_proc ()
{
    const today = new Date ();
    var ddx = today.getFullYear () + "-" + (today.getMonth () +1)
    ddx += "-" + today.getDate ()

    return ddx
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")
const key_in:string = Deno.args[0]
const population_in:string = Deno.args[1]
console.log(key_in)
console.log(population_in)

const url = "http://localhost:5984/nagano/" + key_in

const parsed = await ky.get(url).json()

console.log(parsed._rev)
console.log(parsed.name)

const url_update = url + '?rev=' + parsed._rev

console.log(url_update)

const date_mod = get_current_date_proc ()

const unit_aa = {"name": parsed.name,
        "population": population_in,
        "date_mod": date_mod}

const result = await ky.put(url_update,{json: unit_aa}).json()
console.log(result)


console.error ("*** 終了 ***")
// ---------------------------------------------------------------
```

実行

```bash
deno run --allow-net couch_update.ts t2024 3562100
```
Deno: CouchDB のデータを読む (Read)

```ts:couch_read.ts
// ---------------------------------------------------------------
//	couch_read.ts
//
//					Jul/28/2020
//
// ---------------------------------------------------------------
import ky from 'https://deno.land/x/ky/index.js'
// ---------------------------------------------------------------
console.error ("*** 開始 ***")

const url = "http://localhost:5984/nagano/_all_docs?include_docs=true"

const parsed = await ky.get(url).json()

for (var it in parsed.rows)
	{
	const key = parsed.rows[it].key
	const value = parsed.rows[it]
	const str_out:string = key + "\t" + value.doc.name
		 + "\t" + value.doc.population + "\t" +  value.doc.date_mod
	console.log(str_out)
	}

console.error ("*** 終了 ***")
// ---------------------------------------------------------------
```

実行

```bash
deno run  --allow-net couch_read.ts
```
【Python】lambda式ってどう使うんだろ？？【殴り書き】【続き-1】

#公開理由
・前日にLambda式のコードをqiitaに投稿してみたのだけど、PEP8違反のものでlambda式の動作を
　確認しているようでは自己成長にもつながらないと思ったから。
　よくネットで転がっているmap関数とかfilter関数の使い方を理解しつつ、lambda式のありがたさを感じてみました。

#前回qiitaに挙げたやつ
【Python】lambda式ってどう使うんだろ？？【殴り書き】【初投稿】
https://qiita.com/sho_cullni/items/aba9a09b30abb20cfd1a


#map関数
####●文法
リストに対して関数の処理を実行して返り値を吐き出す処理をする関数

```
map(関数,リスト等)
```


####●サンプルコード
与えられたリストに対して3倍するコードを作ってみた

```map_test.py
num_list = [-4, -3, -2, -1, 0, 1, 2, 3, 4]

triple_num_list = map(lambda x: x * 3, num_list)
print(list(triple_num_list))
```

もしdefを使って上記コードを再現する場合は例えば以下のようになる

```
def triple(x):
    x = x * 3
    return x

num_list = [-4, -3, -2, -1, 0, 1, 2, 3, 4]
print(list(map(triple,num_list)))
```

上記2つのコードを実行した際の出力結果は以下になる

```
[-12, -9, -6, -3, 0, 3, 6, 9, 12]
```


#filter関数
####●文法
リスト等に対して、関数を実行して条件に当てはまるもの（Trueになる）ものだけ返り値として吐き出す処理をする関数

```
filter(関数,リスト等)
```

####●サンプルコード
与えられたリストに対して3の倍数だけ取り出すコードを作ってみた
（世界のナベアツ感）

```filter_test.py
num_list = [1, 2, 3, 4, 5, 6]
aho = filter(lambda x: x % 3 == 0, num_list)
print(list(aho))
```

もしdefを使って上記コードを再現する場合は例えば以下のようになる

```
def ahoaho(x):
    for i in x:
        if i % 3 == 0:
            aho.append(i)

aho = []
num_list = [1, 2, 3, 4, 5, 6]

ahoaho(num_list)
print(list(aho))
```

上記2つのコードを実行した際の出力結果は以下になる

```
[3, 6]
```

#感想
・確かに、defで関数をいちいち定義するより簡単にコードする事が出来そう。。。！
・filter関数とlambda式の合わせ技は、Webスクレイピングで使えそう。今後良い感じに理解出来たらqiitaに挙げてみます。

#sorted関数、max関数、min関数（2020/7/29追記）

コメント頂きましたので、追記させて頂きます！
毎度コメントありがとうございます！(^^)/
defで書くとどうなるか、については今後更新していければと・・・！

また、正確にはlambda関数ではなく、lambda式となっております。失礼致しました。
修正させて頂きました！

####●文法
・それぞれ以下の文法で以下のことを行えます
sorted関数・・・関数の結果に合わせて昇順や降順にソートする。
max関数　 ・・・関数の結果に対して最も大きいデータを取り出す。
min関数 　・・・関数の結果に対して最も小さいデータを取り出す。

```
sorted(リスト等,関数)　・・・maxやminも同様なので一緒に覚えてしまうと良いかもです！
```

####●サンプルコード
・題材としてはあまり良くないのかもしれないですが、イメージしやすそうなコロナウイルス感染者数で
　ソートしてみたり、一番感染者の多い県を出してみたり、その逆をやってみたりします。

```sample.py
corona_infected = [["Tokyo", 11611],["Saitama", 2142],["Chiba",1512],["kanagawa", 2283]]
 
#sorted関数、max関数、min関数のコード例
corona = sorted(corona_infected, key=lambda x: x[1])
corona_max = max(corona_infected,key=lambda x: x[1])
corona_min = min(corona_infected,key=lambda x: x[1])

#コンソールに出力させる
print(corona_infected)
print(corona)
print(corona_max)
print(corona_min)
```

上記2つのコードを実行した際の出力結果は以下になる

```
[['Tokyo', 11611], ['Saitama', 2142], ['Chiba', 1512], ['kanagawa', 2283]]
[['Chiba', 1512], ['Saitama', 2142], ['kanagawa', 2283], ['Tokyo', 11611]]
['Tokyo', 11611]
['Chiba', 1512]
```
Deno: CouchDB のデータを作成 (Create)

```ts:couch_create.ts
// ---------------------------------------------------------------
//	couch_create.ts
//
//					Jul/28/2020
//
// ---------------------------------------------------------------
import ky from 'https://deno.land/x/ky/index.js'
// ---------------------------------------------------------------
console.error ("*** 開始 ***")

const url_collection = "http://localhost:5984/nagano"

const parsed = await ky.delete(url_collection).json()

console.log(parsed)

const result = await ky.put(url_collection,{}).json()

console.log(result)

const dict_aa = data_prepare_proc ()

for (var key in dict_aa)
	{
	const url = url_collection + "/" + key
	const rr = await ky.put(url,{json: dict_aa[key]}).json()
	console.log(rr)
	}

console.error ("*** 終了 ***")
 
// ---------------------------------------------------------------
function data_prepare_proc ()
{
	var dict_aa : {[key: string]: any} = new Object()

	dict_aa = dict_append_proc (dict_aa,'t2021','長野',31496,'2014-9-12')
	dict_aa = dict_append_proc (dict_aa,'t2022','松本',93128,'2014-2-15')
	dict_aa = dict_append_proc (dict_aa,'t2023','上田',74216,'2014-11-2')
	dict_aa = dict_append_proc (dict_aa,'t2024','小諸',38124,'2014-5-22')
	dict_aa = dict_append_proc (dict_aa,'t2025','岡谷',42357,'2014-9-14')
	dict_aa = dict_append_proc (dict_aa,'t2026','塩尻',67283,'2014-8-12')
	dict_aa = dict_append_proc (dict_aa,'t2027','茅野',36251,'2014-3-21')
	dict_aa = dict_append_proc (dict_aa,'t2028','飯田',54623,'2014-7-26')
	dict_aa = dict_append_proc (dict_aa,'t2029','中野',21847,'2014-10-2')
	dict_aa = dict_append_proc (dict_aa,'t2030','諏訪',48392,'2014-12-20')
	dict_aa = dict_append_proc (dict_aa,'t2031','駒ヶ根',51875,'2014-2-7')
	dict_aa = dict_append_proc (dict_aa,'t2032','佐久',69234,'2014-5-17')
	dict_aa = dict_append_proc (dict_aa,'t2033','伊那',31897,'2014-6-19')
	dict_aa = dict_append_proc (dict_aa,'t2034','千曲',59718,'2014-3-30')

	return  dict_aa
}   

// ---------------------------------------------------------------
function dict_append_proc (dict_aa: {[key: string]: any},id_in:string,
	name_in:string,population_in:number,date_mod_in:string)
{
	var unit_aa:{[key: string]: any} = new Object()
	unit_aa['name'] = name_in
	unit_aa['population'] = population_in
	unit_aa['date_mod'] = date_mod_in

	dict_aa[id_in] = unit_aa

	return	dict_aa
}

// ---------------------------------------------------------------
```

実行

```bash
deno run --allow-net couch_create.ts
```
Linux上のPythonアプリからAmazon RedshiftにODBCでデータ連携

#はじめに

この記事では、DataDirectドライバを利用し、Linux、UNIX上のPythonアプリケーションからAmazon RedshiftにODBCで簡単にデータ連携する方法を解説します。


##unixODBCをインストールする
１、以下のコマンドで、unixODBCパッケージをインストールします。

CentOSの場合

```console
sudo yum install unixODBC-devel unixODBC
```

Ubuntu/Debianの場合

```console
sudo apt-get install unixODBC-dev unixODBC
```

２、unixODBCのインストール後、
/home/<user>/Progress/DataDirect/ODBC_80_64bit/odbcinst.ini

の内容を、

/etc/odbcinst.ini

に貼り付けます。


##Amazon Redshift用DataDirectドライバのインストール
１、<a href="https://www.ashisuto.co.jp/datadirect/app_download/" target="_blank">DataDirect ODBC Driver for Amazon Redshift</a>をダウンロードします。
２、以下のコマンドを実行し、パッケージを展開します。

```console
ar -xvf PROGRESS_DATADIRECT_ODBC_REDSHIFT_LINUX_64.tgz
```

３、binファイルを実行し、ドライバをインストールします。

```console
./ PROGRESS_DATADIRECT_ODBC_8.0_LINUX_64_INSTALL.bin
```

４、インストール完了後、インストールフォルダに移動し、シェルスクリプト odbc.sh または odbc.csh を実行し、環境変数を設定します。

５、これで3つの環境変数が設定されます。正しく設定されているかどうかを確認し、先に進みましょう！

```console
[progress@centos7264 ODBC_80_64bit]$ echo $LD_LIBRARY_PATH && echo $ODBCINI && echo $ODBCINST
/home/progress/Progress/DataDirect/ODBC_80_64bit/lib:/home/progress/Progress/DataDirect/ODBC_80_64bit/jre/lib/amd64/server
/home/progress/Progress/DataDirect/ODBC_80_64bit/odbc.ini
/home/progress/Progress/DataDirect/ODBC_80_64bit/odbcinst.ini
```

#PythonからRedshiftに接続する

１、Linux、Unix上yPthonアプリケーションよりRedshiftにアクセスするには、pyodbcパッケージをインストールしなくてはなりません。
以下のコマンドでインストールしてください。

```console
pip install pyodbc
```


２、以下のサンプルPythonプログラムで、Redshiftからデータにアクセスしてみましょう。

```console
import pyodbc
 
conn = pyodbc.connect('Driver={DataDirect 8.0 Amazon Redshift Wire Protocol}; HostName=redshift-cluster-1.cy1mp8nn6ntk.us-west-2.redshift.amazonaws.com; Database=dev; UID=awsuser; PWD=Galaxy472; Port=5439')
 
cursor = conn.cursor()
 
## Create Tables
cursor.execute("CREATE TABLE Track ( TrackId INT NOT NULL, Name VARCHAR(200) NOT NULL, AlbumId INT, MediaTypeId INT NOT NULL, GenreId INT, Composer VARCHAR(220), Milliseconds INT NOT NULL, Bytes INT, UnitPrice NUMERIC(10,2) NOT NULL);")
 
cursor.execute("INSERT INTO Track (TrackId, Name, AlbumId, MediaTypeId, GenreId, Composer, Milliseconds, Bytes, UnitPrice) VALUES (1, 'For Those About To Rock (We Salute You)', 1, 1, 1, 'Angus Young, Malcolm Young, Brian Johnson', 343719, 11170334, 0.99);")
 
conn.commit()
 
##Access Data using SQL
cursor.execute("select * from Track")
while True:
    row = cursor.fetchone()
    if not row:
        break
    print(row)
 
##Access Data using SQL
cursor.execute("select * from Artist")
while True:
    row = cursor.fetchone()
    if not row:
        break
    print(row)
```


非常に簡単ですね。

参考記事

<A href="https://www.ashisuto.co.jp/datadirect/connectors/amazon-redshift.html" target="_blank">Amazon Redshiftへのリアルタイムアクセス
</a>

<A href="https://www.progress.com/tutorials/odbc/connect-to-amazon-redshift-using-odbc-from-python-on-linux" target="_blank">DataDirect for Redshift チュートリアル
</a>
SageMakerの学習インスタンスのディレクトリ構成

# 概要
AWS SageMakerで学習用インスタンスを立ち上げ、学習させる際に
依存ライブラリや独自のソースコードを使うための方法をまとめる。

# ディレクトリ構成
\- notebook.ipynb
\- src
　\- train.py
　\- requirements.txt
　\- my_source/
\- lib
　\- library/

## Notebook
今回はMXNetの例を用いる。
notebookで学習インスタンスを立ち上げるパラメータを以下のように設定する。
パラメータ`source_dir`と`dependencies`が依存するディレクトリの設定である。

``` python:notebook.py
from sagemaker.mxnet import MXNet

gluon_bert = MXNet("train.py", 
                  role=sagemaker.get_execution_role(), 
                  source_dir = "src",
                  train_instance_count=1, 
                  train_instance_type="ml.m4.xlarge",
                  framework_version="1.6.0",
                  dependencies=['lib'],
                  distributions={'parameter_server': {'enabled': True}},
                  py_version = "py3",
                  hyperparameters={'batch-size': 16, 
                                   'epochs': 1, 
                                   'log-interval': 1})
```

## src
このディレクトリには、

- 学習用コード`train.py`
- pipでインストールするリスト`requirements.txt`
- `train.py`で依存する独自コード（※`my_source/`などディレクトリに分けてもよい）

等を格納する。
`requirements.txt`は学習時にインストールされる。

##lib
`src`との違いは`lib`にはnotebook上でインストールしたライブラリを入れる点である。
例えばgithubからcloneし、元コードを書き換える必要がある場合に使用する。
注意する点は、notenookインスタンスのOSはamazon linuxであり、学習インスタンスのOSはubuntsである点である。
そのため、OSに依存するパッケージや特に書き換えが必要ない場合は`requirements.txt`に書く方ことをオススメする。

#学習用コードの書き換え
`lib`のディレクトリを反映するため`train.py`内でpathを通す。

```
import sys
sys.path.append('./lib/')
```


# 参考文献
[Amazon SageMaker コンテナライブラリを使用した Docker コンテナの作成](
https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/amazon-sagemaker-containers.html)
２秒で解決。Big Sur （macOS 11 developer Beta）アップデートでHomebrewが使えなくなった時の対処法

# コマンドラインツールのインストールで解決
##エラーメッセージ
>An exception occurred within a child process: NoMethodError: undefined method `path' for nil:NilClass Did you mean? paths

##診断

```shell
brew doctor
```
>Warning: Your Command Line Tools are too outdated.


>警告：コマンドラインツールが古すぎます。

##対処法

コマンドラインから最新のコマンドラインツールをインストール

```shell
sudo rm -rf /Library/Developer/CommandLineTools
sudo xcode-select --install
```

もしくは、

デヴェロッパーサイトで最新のコマンドラインツールをインストール。
https://developer.apple.com/download/more/

で、動きました。
vue-routerのrouter.goがsafariで機能しない時の対処法

# はじめに
vue-routerを使ったSPAアプリケーションを開発している時に、router.goメソッドでリロードを実現していましたが、ChromeからSafariに切り替えて検証したら動作しなかったため、対処法を調べてみました。

```javascript
this.$router.go
```

# window.location.reload()でブラウザをリロードする
```javascript
window.location.reload()
```
ウィンドウ毎リロードすれば、safariでもリロードできます！
pythonnetを使って.NETのDLLをpythonから呼ぶときの注意点とエラー対処方法

# pythonnet - Python.NETとは
Pythonから.NET向けのDLLを呼び出すことができるライブラリです．
MITライセンスとなっており，だれでも無償で使うことができます．
[https://github.com/pythonnet/pythonnet](https://github.com/pythonnet/pythonnet)

# 使い方
使い方はこちらの記事が大変参考になりました．
[Pythonから.NETを呼び出す方法とついでにその逆も](https://qiita.com/y-tsutsu/items/0c4561d6478be32e6f8e)

ここでは簡単に紹介します．

## インストール方法
```console
pip install pythonnet
```

## 使用例
test.pyと同じディレクトリにあるABCLIb.dllを使いたい場合．
別のディレクトリにある場合は適宜パスを追加してください．`clr.AddReference('./DEF/ABCLib')`など．

```python:test.py
import clr

clr.AddReference('ABCLib')
from ABCTools import ABCLib

abc = ABCLib()
```
`clr`はCommon Language Runtimeの略のようです．

# 注意点とエラーが起きたとき対処方法
私がpythonnetを使用したときにつまづいたポイントとその対象方法を紹介します．

## .dllを書かない
**エラー：System.IO.FileNotFoundException: Unable to find assembly 'ABCLib.dll'.**
`clr.AddReference`するときに拡張子'.dll'を書いているとこのエラーが発生します。
'.dll'を消してみましょう。

```python
# エラーが発生する例
clr.AddReference('ABCLib.dll')

# エラーが発生しない例
clr.AddReference('ABCLib')
```

## セキュリティを許可する
**エラー：System.IO.FileNotFoundException: Unable to find assembly 'ABCLib'.**
外部から取得してきたdllの場合、ファイルへのアクセスがブロックされていることがあります。
アクセスを許可する設定をしてみてください。
dllファイルで右クリック→プロパティ→全般→最下段の「許可する」にチェック→OK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599958/a6e8fa61-1379-09cf-7070-c9299457598a.png)


## DLLとPythonで64bit/32bitを合わせる
**エラー：System.IO.FileNotFoundException: ファイルまたはアセンブリ 'ABCLib, Version=~~~~~~~~, Culture=neutral, PublicKeyToken=null'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。**

DLLとPythonのbitが合っていないと読み取ることができませんでした。

- Pythonのbitの調べ方

```python:
import sys
print(sys.version)
```

```console:出力
3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)]
```

- DLLのbitの調べ方  
こちらの記事を参考にさせていただきました。[EXE、DLLが32bitなのか64ビットなのか確認する方法 \- Qiita](https://qiita.com/towtow/items/a5c92482cca797456b86)
SSH通信について　まとめたこと

#SSH通信とは
SSH通信とは、Secure Shell の略で、言わばセキュリティの強固な通信方法のこと。
SSH通信を用いて送られている情報は全て暗号化されており、
仮に通信を覗き見をされていたとしても、キーを持っていなければ解読することが出来ないようになっている。


#SSHの仕組み（訂正）
＊当初公開鍵認証では乱数を公開鍵で暗号化しそれを複合するという説明を参照としましたがこれらの説明は間違いであったようです。（@angel_p_57さんご指摘ありがとうございます。下記にリンク貼られているページは非常に詳しくまとまっているのでおすすめです。）

SSHで「公開鍵」と言ってるのは、大抵のケースで「認証鍵」（それ以外に「ホスト鍵」もある）
認証鍵は、サーバにログインするユーザを識別するための手続き(ユーザ認証)で使うデータ
認証鍵の実体は、公開鍵暗号の1種である電子署名における、秘密鍵と公開鍵の鍵ペア
ユーザは秘密鍵・公開鍵(両方)を使ってログインを試み、サーバは公開鍵を使ってユーザを識別する
（何らかの方法でサーバに公開鍵を予め登録する必要がある）


ユーザが自身の秘密鍵を使って署名を生成し、その署名をサーバ側が公開鍵を使って検証できれば、その署名は確かに正当なユーザが作成したものだからと判断し、認証成功ということになる。
これと同時にユーザと公開鍵との対応が適切かどうかも照合が行われる。
Git 自分用めも

# svn を使っていたが、git を使い始めると混乱するところ

## リポジトリの作成

リポジトリを作成するだけ(Bara)と、すでにあるものをリポジトリ管理する用の二つ作成方法がある。

svn だと、基本的には、初めに空のリポジトリを作成する。すでにソースがある状態からは作れなかったはず


## ソースの取得

clone する。

svn だとチェックアウト。これはほぼ同じ。

## svn の更新と、git の pull の fetch と merge
git はローカルリポジトリに mastar と origin/mastar の二つが**実は**存在する。
という前提がわかれば、pull と fetch の違いがすぐわかる。

これは svn にはない発想

* 参考 https://qiita.com/wann/items/688bc17460a457104d7d

## commit と push
commit はローカル、push はリモートへソースを反映する。

svn はコミットのみ。ローカルとリモートの発想がない。

## プルリクエスト
ブランチで作業している場合に行うことができる

小規模だと全員 mastar で作業しているとできない

svn だと基本全員 trunk しか使わない・・・
[jQuery] LeaveNotice jQuery Plugin で外部リンクの場合、一旦ポップアップを表示させる

通常のホームページに設置される外部リンクをクリックされた場合、そのまま遷移させるのではなく、一旦ポップアップを表示させ、「本当に良いですか？」的なのを挟むような機能を求められました。

ググってみたら、LeaveNotice jQuery Plugin が良さそうだったので、導入しました。

```
<script language="javascript" type="text/javascript" src="js/jquery.1.7.1.min.js"></script>
<script language="javascript" type="text/javascript" src="js/jquery.leaveNotice.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/jquery.leaveNotice.css">

<a href="sample.com" class="externallink">リンク</a>

<script type="text/javascript">
$(function(){
  $('a.externallink').leaveNotice();
});
</script>
```

#参考URL
[rewdy/leaveNotice: A jQuery plugin for notifying users of their exiting a page.](https://github.com/rewdy/leaveNotice)
[LeaveNotice Example](http://rewdy.com/tools-files/leaveNotice/example.html)
[外部リンクに対してメッセージを表示できるjQueryプラグイン「LeaveNotice jQuery Plugin」 | BlackFlag](http://black-flag.net/jquery/20091007-708.html)
競技プログラミング練習記 No.57【ABC106練習】

初回 -> [はじめに](https://qiita.com/easychoco/items/a9ae28aca97cfe47091f)

[ABC106](https://atcoder.jp/contests/abc106)を解きました。
4完です！
D問題は解説を見て解きました。

|問題|時間|アルゴリズム|実行時間
|:-:|:-:|:-:|:-:|
| A |  1min |-| 6ms|
| B |  6min |約数| 6ms|
| C |  5min |-| 9ms|
| D | - |二次元累積和| 57ms|

# まとめ
先にまとめを載せます。これ自体は最後に書いてます。

`N`が`i`で割り切れた時、`N`は`N/i`でも割り切れますね。
つまり、「`N`以下のの約数が8個」は「`√N`未満の約数が4個」と言い換えることができます。

二次元累積和についてはこちらのページの「4. 二次元累積和」がわかりやすかったです。
[累積和を何も考えずに書けるようにする！](https://qiita.com/drken/items/56a6b68edef8fc605821)

## A - 	Garden
```c++
  int a, b;
  cin >> a >> b;
  cout << (a - 1) * (b - 1);
```
道をずらして畑の端にもってきた場合の面積と求める面積は同じですね。
この時の面積は縦横それぞれ`A-1`と`B-1`になります。

## B - 105
``` c++
  int n;
  cin >> n;
  int ans = 0;
  int num = 1;
  while(num += 2, num <= n)
  {
    int cnt = 1;
    for(int i = 3; i * i < num; i += 2)
    {
      cnt += (num % i == 0);
    }
    ans += (cnt == 4);
  }
  cout << ans;
```
約数が8個なので、実際に割り切れた数字の個数を数えます。
また、`N`が`i`で割り切れた時、`N`は`N/i`でも割り切れますね。
つまり、「`N`以下のの約数が8個」は「`√N`未満の約数が4個」と言い換えることができます。
平方数を除くため、`√N`「未満」であることに注意です。

見るべき数は奇数であることから、コードでは`for`文の範囲を調整して少し高速化しています。

## C - To Infinity

``` c++
  string s;
  ll k;
  cin >> s >> k;
  for(int i = 0; i < k; ++i)
  {
    if (s[i] != '1')
    {
      cout << s[i];
      return;
    }
  }
  cout << s[k - 1];
```
5000兆回繰り返します。
例えば`2`は長さが2倍ずつ増えていくので、5000兆回繰り返した後の長さは`2^5000兆`ですね。
`K`の上限は10^18ですが、`2^5000兆`はこれを余裕で超えています。
`1`のみが長さが変わりません。

つまり、`S`を先頭から見ていって、`1`以外が来ればその値が答えになります。
`K`文字目まですべて`1`であれば、答えは`1`になります。


## D - AtCoder Express 2
``` c++
int dp[505][505];

  int n, m, q, l, r, ql, qr;
  cin >> n >> m >> q;
  for(int i = 0; i < m; ++i)
  {
    cin >> l >> r;
    dp[l][r]++;
  }

  for(int y = 1; y <= n; ++y)
  {
    for(int x = 1; x <= n; ++x)
    {
      dp[y][x] += dp[y][x - 1];
    }    
  }

  for(int x = 1; x <= n; ++x)
  {
    for(int y = 1; y <= n; ++y)
    {
      dp[y][x] += dp[y - 1][x];
    }    
  }

  for(int i = 0; i < q; ++i)
  {
    cin >> ql >> qr;
    ql--;
    cout << dp[qr][qr] - dp[ql][qr] - dp[qr][ql] + dp[ql][ql] << endl;
  }
```
`dp[l][r]`には、区間`[l, r]`より前に区間が終わる電車の本数が入ります。
例えば、`dp[3][4]`には`[1,2]``[2,3]``[1,4]`などの区間が含まれます。

これは二次元累積和という考え方を使っています。
二次元平面で考えて、`dp[l][r]`には座標`(0, 0)`と座標`(l, r)`を通る長方形の内側にある電車の本数が入ります。
クエリで`ql, qr`が与えられたときは、座標`(ql, ql)`と座標`(qr, qr)`を通る長方形の内側にある電車の本数が答えになります。

これを求めると
`dp[qr][qr] - dp[ql - 1][qr] - dp[qr][ql - 1] + dp[ql - 1][ql - 1]`
という式になり、答えがわかります。

二次元累積和についてはこちらのページの「4. 二次元累積和」がわかりやすかったです。
[累積和を何も考えずに書けるようにする！](https://qiita.com/drken/items/56a6b68edef8fc605821)


以上です。ありがとうございました。
GMO ALTUSでスナップショットからの復元をする場合にハマったこと

# はじめに

GMO ALTUS でスナップショットをコピーして本番を作る機会があったが、予想外にハマってしまって時間を使ってしまったので、備忘録として書き残す。

# うまくいかなかった点
## 仮想マシンの作成

AWS用語と比較すると以下のような対応とすると分かりやすい。

| AWS | GMO ALTUS | 備考 |
|-----|-----------|------|
| スナップショット | スナップショット | ディスクのバックアップ |
| AMI | テンプレート | 仮想マシンの元 |

現在スナップショットが存在するので、手順としては

- スナップショットを使ってテンプレート (仮想マシンの元) の作成
- 仮想マシンをローンチ

となる。

その後、仮想マシンに Public IP アドレスを割り振り、NATの設定を済ませたが、ここは新規サーバー構築の時と手順は同じ。


## コンソールが動かない

外部から SSH してもつながらない（もちろんセキュリティグループは空けている)。
そのため、GMO ALTUS にあるコンソールから入って設定しようとしたが、これもつながらない。

これだが、**Google Chromeでは動かず、Firefoxでは動いた** 。
そのため、コンソールが動かないのであればブラウザを変更して実施すればよい。


## 外部からの SSH 接続ができない

元々動いていたサーバーと同様の設定をしたはずなのだが、外部からSSH接続ができない。
そこでGMO ALTUS のコンソールを使ってログインして内部から見てみると、そもそも内部から外部に通信ができない。
原因はネットワーク系の設定が古いサーバーのままになっており、これを現在の設定に合わせてやる必要があった。

今回は CentOS 系だったので  `/etc/sysconfig/network-scripts/ifcfg-eth0` ファイルに書き込まれていたので、ここのIPアドレスとゲートウェイを適切なものに変更し、サーバーを再起動することで対処できた。

### 補足; `:` が打てない場合の対処

`vi` で重要な `:` だが、GMO ALTUSに限らずうまく入力できないケースがある。
この場合、`ZZ` によって保存して終了、が可能である。

## 稼働中のサーバーにセキュリティグループを追加...したかった

一時的に開発用途で問題切り分けのためにセキュリティグループを追加しようとしたのだが、その項目が存在しない。
マニュアルを見る限り、サーバー稼働時にしかセキュリティグループは設定できないらしい。 AWSに慣れてるとこのあたりは「うーん、不便」となる。

https://helpcenter.gmocloud.com/altus/s/article/ch-3509
rails console環境下でスクリプトを実行をする。


### 経緯
`rails console`環境下でbenchmarkを取りたい場面があった。`rails console`環境下で以下のように1行ずつ実行するのも手間で、ファイルのスクリプトを読み込む手法が個人的によかったので記録に残す。

```
Loading development environment (Rails 6.0.3.2)
[1] pry(main)> require 'benchmark'
=> false
[2] pry(main)> def benchmark(try_num:)
[2] pry(main)*   
```


### 手順

１、`rails console`コマンドをターミナル上で実行。

```
$ rails c
Loading development environment (Rails 6.0.3.2)
[1] pry(main)> 
```


２、`load "[ファイル名]"`でファイルに記載されたスクリプトを読み込んで実行することができる。
スクリプトが実行されるので、ファイル内に定義した変数やメソッドをコンソール上で利用できる。

```
[1] pry(main)> load "benchmark_script.rb"
=> true
```

ちなみに、`benchmark_script.rb` の中身としては以下の通り。オブジェクト型の配列のサイズが大きいregionsと小さいcountriesでsampleメソッドのパフォーマンスを分析する。`rails console`環境下であるので、railsアプリケーション内で定義したモデルなども利用できる。

```ruby:benchmark_script.rb
def benchmark(try_num:)
  # SQL 出力制御をする。
  old_logger = ActiveRecord::Base.logger
  ActiveRecord::Base.logger = nil

  regions = Region.all
  countries = Country.all
  Benchmark.bm(10) do |x|
    x.report('region'){ try_num.times { regions.sample } }
    x.report('country'){ try_num.times { countries.sample } }
  end
  # SQL 出力抑制を元に戻す
  ActiveRecord::Base.logger = old_logger
  nil
end
```

3、`benchmark_script.rb`て定義した`benchmark`メソッドを実行。結果として、sampleメソッドは配列のサイズは速度に影響しないことがわかる。

```
[2] pry(main)> benchmark try_num:10000
                 user     system      total        real
region       0.003220   0.000101   0.003321 (  0.003317)
country      0.002791   0.000147   0.002938 (  0.002952)
=> nil
```

###備考
Railsアプリケーション内の修正（モデル内コードを一部書き換えた etc..）があった場合には、その修正分を反映させるために`rails console`を再起動しないといけない。その際には、以下の`reload!`コマンドが便利です。（今まで、`exit`してから`rails console`を立ち上げていた・・・）

```
[11] pry(main)> reload!
Reloading...
=> true
[12] pry(main)> 
```
Ruby on Rails から Open Distro for Elasticsearch に接続する

# この記事について

Ruby on Rails から Docker 上の Open Distro for Elasticsearch に接続する方法を記載します。

# Open Distro for Elasticsearch とは

[Open Distro for Elasticsearch](https://opendistro.github.io/for-elasticsearch/) は Elasticsearch のディストリビューションで、 [Amazon Elasticsearch Service](https://aws.amazon.com/jp/elasticsearch-service/) で使われているものです。

# Docker

[公式のドキュメント](https://opendistro.github.io/for-elasticsearch-docs/docs/install/docker/)を参考に docker-compose で Open Distro for Elasticsearch を立ち上げます。
今回はシングルノードで立ち上げています。

```yaml:docker-compose.yml
version: "3"
services:
  elasticsearch_open_distro:
    image: amazon/opendistro-for-elasticsearch:1.9.0
    environment:
      - discovery.type=single-node
      - cluster.name=elasticsearch
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - 9200:9200
```

# Ruby on Rails から接続

[elasticsearch-rails](https://github.com/elastic/elasticsearch-rails) と [elasticsearch-model](https://github.com/elastic/elasticsearch-rails/tree/master/elasticsearch-model) を使います。

```:Gemfile
gem 'elasticsearch-model'
gem 'elasticsearch-rails'
```

素の Elasticsearch と違い Open Distro for Elasticsearch は localhost の場合も https で接続しなければなりません。
よって initializer は以下のように書きます。
localhost の場合は `transport_options` で ssl の verify を false にしています。
`ELASTICSEARCH_USER` と `ELASTICSEARCH_PASSWORD` はデフォルトでは両方 admin を使うと接続することはできます。

```ruby:config/initializers/elasticsearch.rb
Elasticsearch::Model.client = Elasticsearch::Client.new(
  host: 'localhost',
  port: 9200,
  user: ENV['ELASTICSEARCH_USER'],
  password: ENV['ELASTICSEARCH_PASSWORD'],
  scheme: 'https',
  transport_options: {
    ssl: {
      verify: false,
    },
  },
)
```

これで接続することができました。
[elasticsearch-rails の Usage](https://github.com/elastic/elasticsearch-rails#usage) の手順で接続を確認することができます。
python フォルダを指定or作成してから、スクリーンショットを保存する。


結論
----------------

ディレクトリの生成は os.mkdir(path)
スクリーンショットの撮影は pyautogui.screenshot()
スクリーンショットの保存先は save("保存先")

[※path指定方法](https://techacademy.jp/magazine/18986)


具体例
----------------

```python:全コード
import os
import pyautogui
import time
import datetime

# 保存先path
h_path = "フォルダを保存したい先をここに記入" #例えば、Macなら /Users/"username"/Downloads/
# スクショ回数(回)
times = 3
# スクショ間隔(秒)
span = 1
# 出力フォルダ頭文字
h_foldername = "統計分析"
# 出力ファイル頭文字
h_filename = "資料"

# 出力フォルダ作成(フォルダ名：頭文字_年月日時分)
folder_name = h_foldername + "_" + str(datetime.datetime.now().strftime("%Y%m%d%H%M"))
path = h_path + folder_name
os.makedirs(path, exist_ok=True)

for i in range(times):

    # 画像に名前を付ける
    filename  = h_filename + '_{0:04d}.png'.format(i)+ "_" + str(datetime.datetime.now().strftime("%Y%m%d%H%M%S"))

    #スクリーンショットを撮る
    s = pyautogui.screenshot()

    # 保存
    s.save(folder_name + '/' + filename)

    # スクショ間隔(秒)
    time.sleep(span)
```


＜補足＞

画像ファイルをナンバリングする際に4桁表記にするため.format(number)を使いました。
{0:04d}'.format(number)
・ 0: 0で埋める
・04d: 4桁


```python:例(10→0010)
number = 10
number_padded = '{0:04d}'.format(number)
print(number_padded)  # => '0010'
```

＜参考＞

こちら大変勉強になりました。
[【Python入門】ディレクトリを簡単に作成する｜os.mkdir・os.makedirs](https://www.sejuku.net/blog/63634)
[【Python】pyautoguiを使ってKindle書籍を自動でスクショするツールを作ってみた！](https://elekibear.com/20200225_01)