OmniAICreator/Qiita-1.07M huggingface dataset:
denoでnpmのモジュールの代替方法を探す

　この記事、自信満々な感じで書いてますが、間違いがある可能性があります。なぜならば、私の英語力が乏しいからです。何か間違いがあったら教えてくださると助かります。

#denoじゃ当然npmは使えません
　denoはnodejsを作り直したいと考えたnodejsの作者が作ったものです。nodejsの様々な悪い点を改善しているわけですが、1つ困った点があります。そう、たくさんある便利なnpmモジュール達が使えないのです。そこら辺の経緯は[Denoの登場でNode.jsの時代は終わるのか？](https://qiita.com/so99ynoodles/items/c3ba2a528052827e3b3c)を読んでいただくと面白いと思います。denoの標準モジュールやサードパーティーライブラリは便利なものもたくさんありますが、実際現時点ではnpmモジュールが使いたい場面が出てくるんじゃないでしょうか。実際私はxml→Jsonへの変換をしたいと思ってそこで困ることになりました。そこで私の調べた対処方法を共有したいと思います。

##①諦めて自分で実装する
　これは誰でも思いつきますよね。denoのいいところの1つとして、githubからimport直接できる事が挙げられます。故に、ちょっとしたモジュールなら自作した方が早そうです。
参考：[Denoの自作モジュールをGitHubから読み込む](https://qiita.com/windchime-yk/items/991c9d9213c8bb467dde)

　しかし、xml変換は時間がかかりそうなので、少しやってみて断念しました。

##②denoのURL変換ツールを使う
 実験的な機能ですが、npmのモジュールをインポートする機能がついています。
書き方はこんな感じです。(xml2jsonを使う場合)


```ts
// npm:パッケージよりあとはpackage.jsonのmainに記載されているファイル名を入れてください。
import * as xml2json from 'https://deno.land/x/npm:xmltojson/lib/xmlToJSON.js'

```
>実験的：npm:[package]またはgh:[owner]:[repo]をモジュール名として使用して、任意のリポジトリリポジトリまたはnpmパッケージを解決します。
>※Google翻訳を通しています。
>https://deno.land/x

　しかし、これも駄目でした。require is not defined が出ました。
　おそらくですが、node特有の文法(require()など)がないモジュールならimportできるようです。(大体のモジュールはrequire使っていそうな気がしますが…。)

##③node_modulesからimportする
　本末転倒感ありますが、npmでインストールしたローカルのパッケージを使う方法もあります。[How to use npm module in DENO?](https://stackoverflow.com/questions/61821038/how-to-use-npm-module-in-deno)を参考にしています。

```ts
import { createRequire } from "https://deno.land/std/node/module.ts";

const require = createRequire(import.meta.url);
const xml2json = require("xml2json");
```

　これも②と同じ理由で駄目でした。

##④CDN(Content Delivery Network)プロバイダを使う
 これも[How to use npm module in DENO?](https://stackoverflow.com/questions/61821038/how-to-use-npm-module-in-deno)を参考にしています。
　3つのjsモジュール用CDNプロバイダの中で、必要なモジュールがあるものを選択して使ってください。
>Also take a look at CDN providers, that can auto-convert npm packages to ES Modules (ESM):
>Pika CDN
>jspm.io
>unpkg.com with ?module query parameter

>https://stackoverflow.com/questions/61821038/how-to-use-npm-module-in-deno

　ただし、これらのCDNプロバイダの安全性などは私の方では調べていないので、自己責任でお願いします。
　私はこの方法でなんとかxmlをJsonへ変換するモジュールを見つけました。

　こんな感じです。

```ts
import * as xmlParser from 'https://cdn.pika.dev/fast-xml-parser@^3.17.3';
```

<details><summary>※CDNとは</summary><div>
>CDNとは「Content Delivery Network」の略です。同一のコンテンツを、 多くの配布先、例えば多くのユーザーの端末に効率的に配布するために使われる仕組みです。

>手法としては、 まず配布先に近いネットワーク(カスタマーエッジと呼ばれます)に、コンテンツを配布するサーバ(ここではエッジサーバと呼びます)を接続します。 次にあらかじめエッジサーバに、配布するコンテンツのコピーを置いておきます。 最後に、ユーザーがコンテンツにアクセスする時には、ネットワーク的に最も近いエッジサーバに誘導します。

>ユーザーの視点では、レスポンスが早く、そしてダウンロードが速くなります。 コンテンツ提供者の視点では、オリジナルファイルを置いているサーバ(オリジンサーバと呼ばれます)へのトラフィック集中が避けられる、 サービスの耐障害性を高められる、といったメリットがあります。

>具体的にはソフトウェアのバージョンアップに伴うファイルの配布、 動画の配信などに使われています。

>https://www.nic.ad.jp/ja/basics/terms/cdn.html</div></details>

##まとめ

　今回紹介したのは、下記の4つの方法です。
①諦めて自分で実装する
②denoのURL変換ツールを使う
③node_modulesからimportする
④CDN(Content Delivery Network)プロバイダを使う
　今後denoが普及すれば必要ないですが、現段階では選択肢の1つとしてこれらの方法を検討していただくと良いのではないでしょうか。
ソリューションエクスプローラーにSettings.settingsが無い時の追加の仕方

WPF(.NET Core)のwindows desktop appを作ってて、
Settings.settings を使いたかったんですが
ネット検索の記事どおりにはいかなかったので
若干試行錯誤した結果を記します。

１．ソリューションエクスプローラでPropertiesが無い状態

![2020-06-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/68a36fe9-b61d-a419-bc8d-9f523f03eea3.png)

２．ソリューションを右クリックすると
![2020-06-17 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/450fb1ad-b861-d033-9c8d-c75bcb2d9b1b.png)

３．↑の画面でプロパティを選ぶと↓になる。
![2020-06-17 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/61171e58-6d05-d40b-8fc0-66570e4d707f.png)

４．左のペインで「リソース」をクリックすると↓
![2020-06-17 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/490689f8-95c2-f31f-fc96-8380a0fe953e.png)

５．で、真ん中の「このプロジェクトには規定のリソースファイルが…（中略）…ファイルを作成するには、ここをクリックしてください」をクリックすると↓の画面に。
![2020-06-17 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/a827ab97-be15-2e94-d26c-b92b91ed368b.png)

６．で↑のように　Properties で右クリックして　追加→新しい項目　を選ぶと↓の画面

![2020-06-17 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/6c370aaa-c8ef-0cb0-a540-8935852e75f4.png)

７．「設定ファイル」を追加します。もし名前を変えたければ変えて下さい。
![2020-06-17 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/b2c36e0c-189d-0ef3-f708-dd532e7f9b0e.png)

８．これで　ようやく、Settings.setting が使えるようになりました。

あとは、[こちら](https://qiita.com/tera1707/items/2ebc0e5c48dc5226f60c)などを参考にして作って下さい。
macOSの純正メモアプリでメモが消失する

# 環境
iPhone:iPhoneSE(2020)
mac:MacbookAir(2020)
iOS:13.5.1
macOS:10.15.5
メモ:4.7
# 再現手順
①iPhoneで編集中のメモをmac側で開ける設定(Handoff)をオンにする。同期もオンにする。mac側のメモアプリは閉じておく。
②iPhone側で適当な書類をスキャンしたメモを作成する。この書類はなんでも良いが、ちゃんと四角い方が再現率が高かった。書類の保存直後、メモのキーボードが出てきているので、そのままにして直後に③を実行する。
<img width="65" alt="スクリーンショット 2020-06-17 12.00.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638786/e8ecd30c-6569-965d-f174-34b07e9740ae.png">
1の設定がうまくいっていれば、dockにこのようなアイコンが表示されます。
③このアイコンをmacでクリックする。
④おそらくうまく読み込まれず、リストの一番下にスクロールして「1年1月1日」のメモが現れる。リストの一番上にスクロールするとメモが表示されないか、表示されても一瞬できえる。もしも消えなくてもメモを表示しようとすれば消える。
⑤mac/iPhone双方でメモを閉じる。両方閉じて(mac,iPhoneの順で成功)から両方開く(iPhone,macの順で成功)。iPhone側はリストビューで待機。
⑥しばらくすると、うまくいっていればiPhone側のメモが勝手に消える。「最近削除した項目」にも残らず、完全に消失する。
# 雑感
手元の環境では5回ほど再現しました。すでに2度この手順でメモを失っています。返して…………。
swiperの矢印色変更

##swiperの矢印をデフォルト色から任意の色に変更したい><
######すーぐ忘れちゃうのでめも！


```Javascript:.html
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
```

を

```Javascript:.html
<div class="swiper-button-prev swiper-button-black"></div>
<div class="swiper-button-next swiper-button-black"></div>
```
swiper-button-prev(next)の後ろに swiper-button-任意の色ってやるだけ！
<br>
そもそもの画像変えてみてもいいかもなあ〜〜
Mithril.js Router の応用 - レイアウト、複数コンポーネントを考えた 実用編

# Mithril.js Router の応用 - レイアウト、複数コンポーネントを考えた 実用編

例えば `http://localhost/page1`というURLへのアクセスは `Page1Component` を表示して、`http://localhost/page2` は `Page2Component` を表示したい場合です。

もし、1つの URL が1つのコンポーネントだけで構成されているなら、Mithril.js では、オフィシャルのドキュメントにも書かれている通り簡単です。
ですが、もし1つのURL が1つ以上のコンポーネントで構成されて、共通箇所が有る場合、例えばメニュー等がふくまれコンポーネントが入り組んでいる場合は、作成にコツがいります。

## 基本 : 1つのURLが1つのコンポーネント

おさらい。これは以下の通りで、特に説明の必要もないと思います。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310537/67bfd29d-9ef5-1ef6-13f9-2687905b4536.png)

```tsx
m.route(document.body, '/page1', {
	'/page1' : Page1Component,
	'/page2' : Page2Component,
}
```
`http://localhost/page1` から `http://localhost/page2` へ切り替わるときには、`<Page1Component>` の DOM は削除され、`<Page2Component>` の DOMが作成されます。特に何も問題となることは無いはずです。


## 1つのURLが2つ以上のコンポーネントで、共通箇所が有る場合

この場合は注意が必要です。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310537/d8aab492-17c1-4907-4bb1-2ee94110cbf8.png)

`http://localhost/page1` から `http://localhost/page2` へ切り替わるときには、`<Page1Component>` の DOM は削除され、`<Page2Component>` の DOMが新しく作成されるのは良いとして、
問題は、共通箇所である `<MenuComponent>` の DOM が削除されて、再びDOMが再作成されると厄介な問題が発生します。

具体的には `<MenuComponent>` に使うようなものですから、クリックしたときにCSSアニメーションなどをつけたり、ログインユーザーなどの変数を持っていたりする場合は少なくありません。もしDOM が削除、再作成されるようなことがあれば、CSSアニメーションが途切れたり、画面のチラつきなど、なにかと問題が発生するのです。これは良くは有りません。

これらを防止するために Mithril Router では [RouteResolver](https://mithril.js.org/route.html#routeresolver) というものが用意されています。
この [RouteResolver](https://mithril.js.org/route.html#routeresolver)を使えば、同じコンポーネントのDOMを 削除、再生成 されることを防げます。

```tsx
class LayoutComponent {

	public view(vnode){
		return (
			<div>
				<div class="menu">
					<MenuComponent />
				</div>
				<div class="main">
					{ vnode.children }
				</div>
			</div>
		);
	}
}

class Page1Component {
	// .....
}

class Page2Component {
	// .....
}

const handleOnmatch = ()=>{
	window.requestAnimationFrame(()=>{
		window.scrollTo(0, 0);	// ページ切り替え時 スクロールバーを上部へスクロール
	});
	return;
};


m.route(document.body, '/page1', {
	'/page1' :  {
		onmatch: handleOnmatch,
		render: ()=>{ return <LayoutComponent><Page1Component /></LayoutComponent>; }
	} ,
	'/page2' :  {
		onmatch: handleOnmatch,
		render: ()=>{ return <LayoutComponent><Page2Component /></LayoutComponent>; }
	} ,
}
```

実際のコードを書く場合には、コンポーネントを1つにまとめる `<LayoutComponent>` 等のコンポネントで囲っておくのが良いでしょう。

他にも、ページが切り替わった時にブラウザは上部へスクロールするのがブラウザの一般的な動作です。`onmatch` でページ切り替え時 スクロールバーを上部へスクロールするようにしています。これで、ずいんぶん印象が違ってきますので、入れておくのが良いとは思います。
Sorbetを使った静的型付けRuby

Scala, dartなどの静的型付けをやってきて、久しぶりにRubyを触ってみると動的型付けが辛い。
Ruby3からは静的型付けが公式で入るらしいけど、それまでは[Sorbet](https://sorbet.org/)で凌ぐのが良さげ。

# Sorbet
Ruby2系でも使える静的型チェックをやってくれるgem。
段階的に既存プロジェクトに導入していけるのが強み。

# Install
```ruby:Gemfile
gem 'sorbet', :group => :development
gem 'sorbet-runtime'
```
```bash
bundle install
srb init
srb tc
```
`srb init`で初期化すると、srb関連の機能が使えるようになる。
`srb tc`は後述するsrbを有効化したものについては型チェックして、エラーを出してくれる。

# Use
```ruby
# typed: true
require 'sorbet-runtime'

module A extend T::Sig
  sig {params(left: Float, right: Float).returns(Float)}
  def div(left, right)
    return left / right;
  end
  module_function :div
end

puts A.div(1.0, 2.0)
```
まずは型チェックが通るものから。
1行目は型チェックの有効無効制御で、明示的に指定する必要がある。明示的に向こうにする場合はfalseを指定すればいい。
4行目の`T::Sig`は`sorbet-runtime`に含まれるものだが、これをextendsすることで関数パラメータのIFを記述する`sig`が使えるようになる。
公式でよくやっているtop-levelに`extends T::Sig`する方法もシンタックスとしては通るが、[バグ](https://github.com/sorbet/sorbet/issues/923)で動かないのでmoduleかclassにextendsさせる。
ちなみにメソッドのIFを記述しないなら、1行目の記述だけで良い。

例えば、上記divでString型を返したりするとこんな感じのエラーが出てくる。

```
lib/main.rb:7: Returning value that does not conform to method result type https://srb.help/7005
     7 |    return "";
            ^^^^^^^^^
  Expected Float
    lib/main.rb:6: Method div has return type Float
     6 |  def div(left, right)
          ^^^^^^^^^^^^^^^^^^^^
  Got String("") originating from:
    lib/main.rb:7:
     7 |    return "";
         
```
ただし、Floatに対してIntegerみたいなものだと、実行時までわからないものもある。

```
$ srb tc
No errors! Great job.
$ ruby lib/main.rb
Traceback (most recent call last):
...
Expected type Float, got type Integer with value 1 (TypeError)
Caller: lib/main.rb:12
Definition: lib/main.rb:6
```

# IDE Support
vscodeの場合は[sorbet-lsp](https://marketplace.visualstudio.com/items?itemName=danhuynhdev.sorbet-lsp)を入れるだけでいい。
最もvscodeのプラグイン自体はまだ開発中らしく不安定だが、十分役に立ってくれる。
![スクリーンショット 2020-06-17 12.19.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657207/b7b11e38-042c-cfa3-2b64-07588fff893c.png)
git hooksのpre-commitでmasterにそもそもコミットさせないようにする

# 課題
うっかりmasterにコミットしてしまう事故がよく発生するので、そもそもpre-commitでコミットする前の段階でエラーで弾くようにした。

# 前提
mac OS 10.15.4
windows10

# 準備
git/hooks配下に「pre-commit」ファイルを用意する


## コード
`git symbolic-ref HEAD --short`で現在のブランチ名を取得
masterと文字列比較をすることで、自分が今masterブランチ以外のブランチにいるということを確認している

```sh

#!/bin/sh
branch=`git symbolic-ref HEAD --short`
if [ ${branch} = master ]; then
  cat <<\EOF
  エラー：masterブランチにcommitはできません。
EOF
	exit 1
fi
```


# 参考
[pre-commit hookでmasterへのcommitを禁止した](https://blog.n-z.jp/blog/2014-02-07-pre-commit-hook.html)
Dialogflow Messenger の要素は getElementsByClassName などで取得できないっぽい

Dialogflow Messenger を使って埋め込んだボットの`input`要素の値を取得したいとか思ったけど、以下のようなコードでは上手くいかない。

```javascript
var value = document.getElementsByClassName('input-box-wrapper');

var value = jQuery('.input-box-wrapper').children('input').val();
```


どうやらiflameで埋め込まれたコードと同様に`script`と`df-messenger`で埋め込まれたものも取得できないようだ。
https://stackoverflow.com/questions/54171882/how-to-get-text-from-iframe-of-dialogflow-web-demo
Rustでクリーンアーキテクチャを組む時DIするサンプルコード

# はじめに

Rustでクリーンアーキテクチャを組もうとしていて、うまくレイヤーを分離できませんでした。
思想というよりは単にtraitやジェネリクスの正しい書き方を知らなかっただけでかなりの時間を要してしまったので、自分のメモを兼ねて書いてみようと思います。

構成としては
`DB -> Repository -> Service`というようなレイヤーがあった時に、いかに分離(=**DI**)するかを想定しています。

# 関連型 + 関連関数での実装
```rust

#[derive(Debug)]
struct User {
    age: u8
}

struct PgDatabase;

// 関連型を用いたトレイト
trait Repository {
// 関連型
    type CreateRequest;
    type CreateResponse;

// 関連関数
    fn create(request:Self::CreateRequest) -> Self::CreateResponse;
}

impl Repository for PgDatabase {
    // add code here
    type CreateRequest = u8;
    type CreateResponse = User;
    fn create(age: u8) -> User {
        User { age }
    }
}

struct Service<U:Repository>(U);

impl <U:Repository> Service<U>{
    pub fn new_with_age(&self, age: U::CreateRequest) -> U::CreateResponse {
        U::create(age)
    }
}

fn main() {
    let db: PgDatabase = PgDatabase;
    let service = Service::<PgDatabase>(db);
    let user = service.new_with_age(20);
    dbg!(user);
}

```

# ジェネリクスとメソッドでの実装

```rust

#[derive(Debug, Clone, Copy)]
struct User {
    id: u16,
    age: u8
}

struct PgDatabase{
    // DB機能のモックです
    next_user_id: u16,
    users: Vec<User>
}

// generic trait
trait Repository<T,U,V> {
    fn create(&mut self, new_params:T) -> U;
    fn find_by_id(&self, id: V) -> Option<&U>;
}

impl Repository<u8, User, u16> for PgDatabase {
    // add code here
    fn create(&mut self, age: u8) -> User {
        let u = User{ age, id: self.next_user_id };
        self.next_user_id = self.next_user_id + 1;
        self.users.push(u);
        u
    }

    fn find_by_id(&self, id: u16) -> Option<&User> {
        self.users.iter().find(|user| { user.id == id })
    }
}

struct Service<U:Repository<u8, User, u16>>{
    repository: U
}

impl <U:Repository<u8, User, u16>> Service<U>{
    pub fn new_with_age(&mut self, age: u8) -> User {
        self.repository.create(age)
    }
}

fn main() {
    let db: PgDatabase = PgDatabase { next_user_id: 0, users: Vec::new()};
    let mut service = Service::<PgDatabase>{repository: db};
    let user = service.new_with_age(20);
    dbg!(user);
}
```

***........その他はパターンを見つけ次第追記予定***

# 終わりに

今の所２つのサンプルしかありませんが、他の実装パターンも追記予定です。
良くない書き方があるかと思いますので、お気づきの際にはご指摘いただければ幸いです。
Ubuntu を使ったWindowsファイルレスキューの仕方

1. 下記からisoイメージをダウンロード
https://www.ubuntulinux.jp/download/ja-remix
ubuntu-ja-20.04-desktop-amd64.iso でよい.

2. isoをusbに書き出すソフト etcher をダウンロードしてインストール
https://www.balena.io/etcher/

3. 1のisoイメージを適当なusbに書き込む

4. USBブートする

5. `sudo fdisk -l` で、マウントする対象ドライブの識別子を確認する  ex. `/dev/sda5`

6. `sudo ntfsfix /dev/sda5` で、ntfs を正常にマウントできるようにしてあげる

7. `sudo umount /dev/sda5`(いらないかも)をして、`sudo mkdir /mnt/d` からの `sudo mount /dev/sda5 /mnt/d`とする

8. あとは煮るなり焼くなり.
starship ターミナルのプロンプトをカスタマイズする

## 背景

ターミナルのプロンプトですが、デフォルトだと見づらくて使いづらいです。
プロンプトはカスタマイズするとGitブランチ名やGitの進捗表示も行えるのでかなり便利になります。

とはいえ、本腰を入れてカスタマイズ始めると日が暮れちゃうのでstarshipを使います。

- https://starship.rs
- https://github.com/starship/starship

## ゴール

![ScreenShot 2020-06-17 11.49.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/fe9c27a1-b7e5-83bf-c744-849b2cbd809e.png)

## 現在のシェルを確認

```
$ echo $SHELL
```

## starshipのインストール

```
$ brew install starship
```

### zshシェルの場合

```
$ echo 'eval "$(starship init zsh)"' >> ~/.zprofile
$ exec $SHELL -l
```

### bashシェルの場合

```
$ echo 'eval "$(starship init bash)"' >> ~/.bashrc
$ exec $SHELL -l
```

### fishシェルの場合

```
$ echo 'eval "$(starship init fish)"' >> ~/.config/fish/config.fish
$ exec $SHELL -l
```

## starshipの設定ファイルの作成

```
$ mkdir ~/.config
$ touch ~/.config/starship.toml
```

## starshipの設定ファイル設定例

```
$ vim ~/.config/starship.toml
add_newline = false

[directory]
truncate_to_repo = false

[time]
disabled = false
```

その他の詳細な設定は公式に詳しく書かれているのでそちらを参照ください。

- https://starship.rs/ja-jp/config

## フォントをインストールする

Gitのアイコンが文字化けするのでフォントをインストールします。

```shell-session
$ brew tap homebrew/cask-fonts
$ brew install font-fira-code --cask
```

ターミナルを開いてフォント設定する。

![ScreenShot 2020-07-03 11.40.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/d0f64103-f605-d118-777e-bb36c18c57e4.png)

Fire Code, Retina, 12の設定が個人的に好き。
競技プログラミング練習記 No.13【ABC144練習】

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

[ABC144](https://atcoder.jp/contests/abc144)を解きました。
5完です。

|問題|時間|アルゴリズム|実行時間
|:-:|:-:|:-:|:-:|
| A |  1min |-|1ms|
| B |  2min |-|1ms|
| C |  9min |因数分解|11ms|
| D | 45min |図形と三角関数|3ms|
| E | 35min |二分探索|138ms|



## A
```c++
	int a, b;
	cin >> a >> b;
	cout << (a < 10 && b < 10 ? a * b : -1);
```
問題文のとおりにやるだけ。

## B
``` c++
	int n;
	cin >> n;

	for(int i = 1; i <= 9; ++i)
	{
		if (n % i == 0 && n / i <= 9)
		{
			cout << "Yes";
			return;
		}
	}
	cout << "No";
```
`1~9`で割って、割り切れた時の答えが`1~9`かを判定します。

## C
``` c++
	ll n;
	cin >> n;

	ll ans = n + 1;
	for(ll i = 2; i * i <= n; ++i)
	{
		if (n % i == 0)
		{
			ans = min(ans, i + n / i);
		}
	}
	cout << ans - 2;
```
素数判定と似ています。`i`の範囲に注意です。
求める移動回数は因数の和ですね。
割り切れた時に、`min`関数を使ってより小さくなるようにしています。

`ans`を`n + 1`で初期化しているのは、`1`で割ったときの答えが`n + 1`になるからです。

始点が`(1, 1)`なので、`(0, 0)`からの移動コスト`2`を引いた`ans - 2`が答えになります。
始点が`(0, 0)`だったら`ans`が答えでした。
(その意味では`ans`という名前はちょっとおかしいですね。。)

## D


``` c++
	const double Rad2Deg = 180.0 / PI;

	double a, b, x;
	cin >> a >> b >> x;

	double v = a * a * b;
	if (x < v / 2.0)
	{
		printf("%.7f\n", atan2(a * b * b, 2.0 * x) * Rad2Deg);
	}
	else
	{
		printf("%.7f\n", atan2(2.0 * (a * b - x / a), a * a) * Rad2Deg);
	}
```
図形の問題です。
水が三角形を作る場合と台形を作る場合で分けました。
求める角度を`θ`として、`x`の式と`θ`の式の2通りで体積を表します。

・水が三角形を作る場合

```math
x = \frac{ab^2}{2 \  tan θ}
```

・水が台形を作る場合

```math
x = a^2b - \frac{1}{2}a^3\tan θ
```

となるので、それぞれ`tanθ`について解きます。
`tanθ`がわかれば、arctangent(`atan2関数`)から答えがわかります。

## E

```c++
	ll n, k;
	cin >> n >> k;
	vector<ll> a(n);
	vector<ll> f(n);

	for(int i = 0; i < n; ++i)
	{
		cin >> a[i];
	}
	for(int i = 0; i < n; ++i)
	{
		cin >> f[i];
	}

	sort(a.begin(), a.end());
	sort(f.begin(), f.end(), greater<int>());

	ll le = -1, re = 1000000000000LL;
	while(re - le > 1)
	{
		ll mid = (le + re) / 2;
		{
			ll tmp_k = 0;
			for(int i = 0; i < n; ++i)
			{
				if (a[i] * f[i] > mid)
				{
					tmp_k += (a[i] * f[i] - mid - 1) / f[i] + 1;
				}
			}
			if (tmp_k <= k) re = mid;
			else le = mid;
		}
	}
	cout << re;
```
これは二分探索ですね。
ABC146の練習で解いたばかりですがまた会えました。2日ぶりの再会です。
二分探索は覚えたばかりですが、二分探索と見抜いて実装までできたので満足です。

`A`を昇順、`F`を降順にソートして、それぞれ掛け合わせた場合が最もコストを少なく抑えられます。
（`A`を降順、`F`を昇順としても問題ありません）
`mid`がチームの最小コストになるのですが、そのコストを実現できるかどうかは`O(N)`で調べられます。
`ceil( (a[i] * f[i] - mid) / f[i] )`の総和が必要な修行回数になるので、
計算した修行回数が入力値の修行回数を超えているかどうかで二分探索の境界を更新します。

右端`re`の初期値は最大コストの`10^6 * 10^6 = 10^12`にしています。
左端`le`の初期値は右端が`0`になるときに合わせました。

以上です。ありがとうございました。
Laravelでバリデーションエラーを日本語化対応する

#はじめに
Laravelはバリデーションルールに沿わないリクエストが送られてきた時、デフォルトで英語の警告文が表示されます。
しかし、日本語で警告文を表示させたい時がほとんどだと思いますので今回は日本語への変更方法についてまとめます。

5分もあれば終わります！

#初期設定
Laravelプロジェクト配下のconfig/app.phpを開いて設定を変更します。
以下の項目を適宜変更していきます。

```config/app.php
//タイムゾーンの変更
'timezone' => 'Asia/Tokyo',

//ロケールの変更(言語のことです)
'locale' => 'ja',

//今は関係ありませんが、ダミーデータを作るさいに日本語でダミーデータを作成してくれます
'faker_locale' => 'ja_JP',
```

configファイルを変更したので、キャッシュクリア系のコマンドを実行しておきましょう。

```
$ php artisan config cache
```

#日本語化したファイル作成

デフォルトの英語警告文はどこに記述されているかと言うと、resources/lang/enフォルダ内にあります。
例えば、resources/lang/en/auth.phpファイルの場合

```resources/lang/en/auth.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are used during authentication for various
    | messages that we need to display to the user. You are free to modify
    | these language lines according to your application's requirements.
    |
    */

    'failed' => 'These credentials do not match our records.',
    'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',

];
```

ここではログイン画面で認証に失敗した場合、画面には

```
These credentials do not match our records.
```
と表示されるはずです。


ここを日本語に直してあげれば良いだけです！

##コピペで超簡単に日本語化する

日本語化ファイルについて、github上で公開してくれている方がいましたので今回はそこから引用してきます！

Laravel-lang
https://github.com/caouecs/Laravel-lang/tree/master/src/ja

自分のLaravelプロジェクト配下にresources/lang/jaフォルダを作成し、あとはこのページの通りのファイルを作成するだけです。

```resources/lang/ja/auth.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are used during authentication for various
    | messages that we need to display to the user. You are free to modify
    | these language lines according to your application's requirements.
    |
    */

     'failed'   => '認証情報と一致するレコードがありません。',
     'throttle' => 'ログインの試行回数が多すぎます。:seconds 秒後にお試しください。',
];
```

試しに、resources/lang/ja/auth.phpを作成してみました。
これで日本語化対応されているはずです。

あとはresources/lang/ja/validation.phpファイルなんかも同様に作成していけば完了です。
今回はここまでにします！

#参考ページ
Laravel-lang：https://github.com/caouecs/Laravel-lang/tree/master/src/ja 
Fred Delrieu氏のgithubアカウントから参照
Kubernetesのマニフェストを書く時に見るリンク集

# サンプルマニフェスト

書籍) 「Kubernetes: Up and Running: Dive Into the Future of Infrastructure」の付属サンプル
https://github.com/kubernetes-up-and-running/examples

書籍) 「Kubernetes完全ガイド」の付属サンプル
https://github.com/MasayaAoyama/kubernetes-perfect-guide

書籍) 「15Stepで習得 Dockerから入るKubernetes コンテナ開発からK8s本番運用まで」の付属サンプル
https://github.com/takara9/codes_for_lessons

書籍) 「Docker/Kubernetes 実践コンテナ開発入門」の付属サンプル
https://gihyo.jp/book/2018/978-4-297-10033-9/support

k8s公式リポジトリのサンプル集
https://github.com/kubernetes/examples

k8sやパブリッククラウドのサンプル集
https://github.com/pulumi/examples
【Git】リモートにプッシュしていないコミットの一覧を取得する。

メモとして残します。


#■やり方
###1.確認したいブランチに移動
```shell
git checkout ブランチ名
```

###2.未コミットを確認。
```shell
git log origin/リモートブランチ名..HEAD
```
上述のリモートブランチ名は基本的には追跡ブランチになるはず。
Alpine Linuxでパッケージ(apk)を使って入れたファイルの一覧を出す

Alpine Linux で、インストールしている apk パッケージに入っているファイルを表示するワンライナーを書きました。

~~標準で入っているものだけで作りたかったんですが、力不足で perl に依存する形になってしまいました……。~~ → **できました！**

# スクリプト

汚いし、長いです。

 `ash` だとヒストリを辿るときに複数行に分けると美しくないので一行バージョンも用意しました。中身は同じです。

```shell
apk info | sort | xargs apk info -L | while read -r l; do if [ `echo -n $l | grep -c contains:` -eq 1 ]; then p=`echo -n $l | sed -E 's/^(.*)\-[^-]+\-r[0-9]+ contains:.*$/\1/'`; elif [ "$l" != "" ]; then echo "$p /$l"; fi; done
```

改行とインデントを加えて、挙動を少しでも分かりやすくしてみました。
https://github.com/keioni/qiita-sample/blob/master/apk_listup_files.sh

```shell:apk_listup_files.sh
apk info | sort | xargs apk info -L |
while read -r l; do
  if [ `echo -n $l | grep -c contains:` -eq 1 ]; then
    p=`echo -n $l | sed -E 's/^(.*)\-[^-]+\-r[0-9]+ contains:.*$/\1/'`;
  elif [ "$l" != "" ]; then
    echo "$p /$l";
  fi;
done
```

# 実行結果

以下のように **"パッケージ名 パス"** のかたちで表示されます。`grep` して使ってください。

```
:
apache2 /usr/sbin/suexec
apache2 /var/www/logs
apache2 /var/www/modules
apache2 /var/www/run
apache2 /var/www/localhost/cgi-bin/printenv
apache2 /var/www/localhost/cgi-bin/printenv.vbs
apache2 /var/www/localhost/cgi-bin/printenv.wsf
apache2 /var/www/localhost/cgi-bin/test-cgi
apache2 /var/www/localhost/htdocs/index.html
apache2-http2 /etc/apache2/conf.d/http2.conf
apache2-http2 /usr/lib/apache2/mod_http2.so
apache2-mod-wsgi /etc/apache2/conf.d/wsgi-module.conf
apache2-mod-wsgi /usr/lib/apache2/mod_wsgi.so
apache2-ssl /etc/apache2/conf.d/ssl.conf
apache2-ssl /usr/lib/apache2/mod_ssl.so
apk-tools /sbin/apk
apr /usr/lib/libapr-1.so
apr /usr/lib/libapr-1.so.0
apr /usr/lib/libapr-1.so.0.7.0
apr-util /usr/lib/libaprutil-1.so.0
apr-util /usr/lib/libaprutil-1.so.0.6.1
apr-util /usr/lib/apr-util-1/apr_crypto_openssl-1.so
apr-util /usr/lib/apr-util-1/apr_crypto_openssl.so
busybox /bin/busybox
busybox /bin/sh
busybox /etc/securetty
:
```

# (旧版) perl

最初に作った `perl` バージョンも、一応そのまま置いておきます。

```
apk info | sort | xargs apk info -L | perl -ne 'if (/^(.*)\-[^-]+\-r\d+ \w+:/) {$p=$1; next} elsif ( !/^$/ ) {print "$p /$_"}'
```
Xplenty入門 Part6: ブラックボックス化しないための仕組み

ETLはどの製品もシンプルなGUIで簡単にパイプラインの構築ができることをを売りにしています。
しかし、作るときはシンプルでも、後々変更したりする際に、以下のような疑問を持ったことは誰しもあるかと思います。

- この処理は何を意図した処理なのか？
- この処理自体が不要では？

過去に自身で作ったものであっても背景や理由を思い出せず、それをトレースするのに時間がかかった苦い経験をお持ちの方は多いのではないでしょうか？
とはいえ自身で作成したものであればまだなんとか対応できたとしても、人が作ったものはドキュメントがないと、解読が難しいのも事実です。しかも、ドキュメントが必ずしも最新ではなく、結局１つ１つの処理を紐解いて確認していかないといけなかった経験のある方は多いのではないでしょうか？

Xplentyでは、こうした問題を解決するための機能として、パイプラインに仕様や注意事項などを直接埋め込むことができるコメント機能があります。この機能により、担当者が退職したためETLパイプラインがブラックボックス化してしまう悲劇を防ぐことができます。

Xplentyのコメント機能はパッケージ編集画面の好きな位置に置くことができ、より直接的にパイプラインの特定の箇所に説明を追加することが可能です。
例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/43a56a71-7c5b-9064-7a95-e2e6f62c13cf.png)

上記の例は簡単なコメントですが、コメントの編集画面では、さらに文字数を使って説明を詳細に記入することも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/6c7555db-7168-db48-6f91-21e3307fde2e.png)

Xplentyでパッケージを作成する際は、ぜひこの機能をフル活用し、メンテナンス時に優しい仕組みを心がけてください。
ESP32のバイトオーダー調査メモ

直ぐに忘れがちなので。

調べた時のコード

```c:main.c

typedef struct __attribute__((packed)) {
	union {
		uint8_t row[8];
		char text[8];
		int64_t longValue;
		int32_t intValue;
		int16_t wordValue;
		int8_t byteValue;
		void * pointer;
		float floatValue;
		double doubleValue;
	};
	uint8_t size;
} test_u;

void app_main() {
	_i("size: %u", sizeof(test_u));

	char text[] = "hello, world!!";
	test_u _64, _32, _16, _8, _8a, _f, _d, _p;
	test_u *u[] = {&_64, &_32, &_16, &_8, &_8a, &_f, &_d, &_p};
	for(int i=0; i<8; i++) memset(u[i], 0, sizeof(test_u));

	_64.longValue = -89750967853ll;
	_32.intValue = 987539l;
	_16.wordValue = -4125;
	_8.byteValue = -112;
	_i("size: %u", sizeof(test_u));
	strncpy(_8a.text, text, 8);
	_f.floatValue = 145.412362980f;
	_d.doubleValue = 819047.10892790;
	_p.pointer = text;

	for(int i=0; i<8; i++) {
		char b[128];
		for(int j=0; j<8; j++) {
			sprintf(b+(j*3), "%2x ", u[i]->row[j]);
		}
		_i("%d: %s", i, b);
	}
	_i("pointer address: %p", text);
}
```


```
size: 9
0: d3 e9 6c 1a eb ff ff ff // -89,750,967,853(dec) -> ff ff ff eb 1a 6c e9 d3(hex) を逆順詰め
1: 93 11  f  0  0  0  0  0 //         987,539(dec) ->  f 11 93(hex)
2: e3 ef  0  0  0  0  0  0 //          -4,125(dec) ->    ef e3(hex)
3: 90  0  0  0  0  0  0  0 //            -112(dec) ->       90(hex)
4: 68 65 6c 6c 6f 2c 20 77
// h(0x68) e(0x65) l(0x6c) l(0x6c) o(0x6f) ,(0x2c) _(0x20) w(0x77) [o(0x6f) r(0x72) l(0x6c) d(0x64) !(0x21) !(0x21)]

// 浮動小数点の内部表現は下記で調査
// https://tools.m-bsys.com/calculators/ieee754.php
5: 91 69 11 43  0  0  0  0 // 145.412362980f -> 0b 0100 0011 0001 0001 0110 1001 1001 0000 (0x43 11 69 90) を逆順詰め
6: d0 65 c5 37 ce fe 28 41 // 819047.10892790 -> 0b 0100 0001 0010 1000 1111 1110 1100 1110 0011 0111 1100 0101 0110 0101 1101 0000
// (0x 41 28 fe ce 37 c5 65 d0)
7: 30 c8 fb 3f  0  0  0  0 
pointer addres: 0x3ffbc830
```

バイトオーダーで単純な逆順になることが確認できました。

32bit以上のデータ型はワード毎のリトルエンディアン、
8975093であれば、0x0088f2f5の88 00 f5 f2になると勘違いしていたので、
改めて、仕様の理解が不十分なことは確認することが大事だと思いました。
Azure Database for MariaDBのデプロイ方法

# 内容
- Azure Database for MariaDBのデプロイ
- my.cnfの設定
- ファイアウォールの設定
- sequel proで接続テスト

# 参考にした記事
https://qiita.com/cherubim1111/items/a9ac21899dfc91e01dda

# Azure Database for MariaDBのデプロイ
- Azure Database for MariaDBサーバーを選択する
![すべてのサービス_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/7671dd49-cf9d-0cd3-0a01-dd694b2b2e9a.png)

- 適当な値を入力してMariaDBを作成する
![MariaDB_サーバーの作成_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/6bf48592-50ab-a81e-64cb-f9c1cbf7fbac.png)

# my.cnfの設定
- サーバー パラメーターでmy.cnfの設定が可能です
![paas-test___サーバー_パラメーター_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/3927677e-9925-0d9c-f4db-224430b2cf44.png)

# ファイアウォールの設定
- ファイアウォールを設定する
![paas-test___接続のセキュリティ_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/f0c1c6ac-4328-fd11-ac06-9ebcce717287.png)

# sequel proで接続テスト
- 概要でサーバ名とサーバー管理者ログイン名を確認する
![paas-test_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/104eb4ad-be48-2065-cc70-b8186fa6166a.png)
- sequel proで接続する
![Sequel_Pro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/1e728a1d-43e0-1853-f093-bbc4fd604379.png)
読書要点「プリンシプルオブプログラミング」第3章 アーキテクチャ根底技法

## アーキテクチャ根底技法

アーキテクチャ根底技法とは、ソフトウェア・アーキテクチャ構築のための基礎原理で、モジュールの設計指針として示される。
多くの経験によって蓄積されてきた型のようなもので、10の技法がある。

### 抽象

抽象とは、概念的な線引きを行うことで、「捨象」「一般化」の2つの作業からなる。
複雑な対象から抽象した概念は、単純で無駄のない、扱いやすい概念となる。
そのため抽象は、複雑なプログラムに挑むときの効果的な道具となる。

捨象では、複雑な対象の持つ要素を捨て去る。
このことで本質的でない問題を視界からそらすことができる。
一般化では、複数の対象が持つ性質から共通項を抽出し、単純な概念へと昇華させることである。
捨象により本質的な情報を露見させ、一般化によって扱いやすい概念へと昇華させることで概念を抽象することができる。

### カプセル化

関連性の強いデータとロジックをひとまとめにし、モジュール化することをカプセル化と呼ぶ。
結びつきの強い概念がまとまり細分化されることで、コードの可読性の向上、結果の局所化、再利用のしやすさの向上といった利点がある。
関係のない要素が混ざらないようにカプセル化すれば、質の高いモジュールを作成することが可能である。

### 情報隠蔽

モジュールでどのような実装をしているのかを、モジュールを呼び出すクライアントから見えなくすることである。
モジュールが受け取ったり引き渡す情報はシンプルになり、クライアントも余計な情報が見えないため使い勝手が良くなる。

### パッケージ化

モジュールを意味のある単位でグループ化することをパッケージ化と呼ぶ。
論理構造でつながるモジュール群を物理構造に格納していく。
モジュールの数が増えて複雑になったソフトウェアに対する解決策となる。
パッケージ化により複雑性が減るだけでなく、結果の局所化やモジュール群の再利用性の向上も見込める。

ソフトウェアの作成時は、モジュールが増えて意味のあるまとまりを持つようになったらパッケージ化するようにする。
パッケージとは機能分解の単位ではなく、ソフトウェアのビルド方法を示すマップで、トップダウン的に作られるものではない。

### 関心の分離

カプセル化やパッケージ化で似たような機能を持つ部分を分離するが、機能だけではなく関心にもとづいて分離することも考えたい。
MVCモデルやアスペクト指向プログラミングは関心の分離を目的とした概念である。
MVCモデルではバックエンドを担当するmodel、フロントエンドを担当するcontroller、GUIに関わるviewという3つの関心事から分離を行う。
プログラミング言語単体では機能の分離に目が行きがちな部分にメスを入れる技術だと言える。
関心の分離により、変更頻度や結果の局所化からソフトウェアの安定性につながるだけでなく、関心で分離されるため開発をそれぞれの関心事に並行して進めやすい。

モジュール化を行うときも関心をできるだけ意識しておきたい。
モジュールの機能に限らず、モジュールの持つべき役割・目的にも着目したモジュール化を行うのが良い。

### 充足性、完全性、プリミティブ性

モジュールが果たすべき抽象の表現の評価についてである。
充足性、完全性、プリミティブ性から評価する。
要は、モジュールは表現したい抽象に対して必要十分であり、モジュール内のそれぞれの要素が独立であるべきだということである。

そのモジュールを呼び出すクライアント目線で使いやすいものを作るべきであり、そのためには必要十分で独立なものを作るようにする必要がある。

### ポリシーと実装の分離

モジュールはポリシーと実装を扱う。
ただし、一つのモジュールの中で、その両方を同時に扱ってはいけない。
ポリシーモジュールはソフトウェアの前提に依存し、利用するロジックや引数の選択を行う。
実装モジュールはソフトウェアの前提に依存しないロジック部で、ポリシーモジュールによって利用される。
実装は安定しており、ソフトウェアの前提の変更によって引きずられることはないが、ポリシーは変化しうる。

結果の局所化、変更頻度の観点からもモジュール化の際にはポリシーと実装の分離に努めたい。

### インターフェースと実装の分離

モジュールを作るときは、インターフェースと実装から構成するようにする。
インターフェースではモジュールが持つ機能を定義しており、クライアントがアクセスするのに必要な引数の名前などを構成するのに留まる。
実装では、機能を実現するのに必要なデータとロジックを持っており、ここにはクライアントからアクセスすることはできない。
この分離を行うことにより、クライアントは使い方が示されているインターフェースのみを把握していればよく、使い勝手が良くなる。
また、保守の観点でもインターフェースを維持したまま実装の修正を行うことができるので結果の局所化につながる。

モジュール同士の呼び出しにおいて、互いにインターフェースのみが使用されるように設計すると良い。

### 参照の一転性

モジュールの要素の定義を一度切りにし、再定義を行わないようにすることである。
再定義を頻繁に行うと、要素の変化に応じた影響が発生しやすい上、コードを追いかけるのが困難になる。

要素に対して単一代入を心がけ、できるだけ要素の再定義を行わないようにするのが良い。
プログラミング言語の機能的には再定義が認められることが多いが、極力その回数を減らして見通しの良いコードを書きたい。

### 分割統治

大きな問題は小さな問題に分割して個別で解決していく。
制御できない大きな問題は制御できるレベルまで分割して考えるのがよい。

設計のときから表現すべき要素を逐一分割していくことで、スムーズな作業につながっていく。
Azure CycleCloudでData Science VMベースのslurmクラスターを作成できない問題への対処法

## 問題
Azure CycleCloudでData Science VM (DSVM) イメージを使用してslurmクラスターを作成しようとしてもエラーが発生しクラスターの立ち上げができない。

- DSVMイメージはmaster, hpc, htcのクラスターに使用する  
- 使用しているイメージのURNは`microsoft-ads:linux-data-science-vm-ubuntu:linuxdsvmubuntu:20.01.09`
    - ※別バージョンのURN (`microsoft-ads:linux-data-science-vm-ubuntu:linuxdsvmubuntubyol:20.01.09`)を使用しても同様のエラーが発生。


下記のようなエラーメッセージが表示されてしまう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/e4763897-127f-f2fa-a956-0eec4184f62a.png)

## 対処法
### 要因
どうやらslurmジョブスケジューラーで使用するmunge userのUID/GIDが競合してしまうことが原因のようです。他のUID/GIDへと変更することで解決できました。

### 手順
master node, htc/hpc nodearraysの設定 (configuration画面)に下記を入力します。

```
munge.user.gid = 994
munge.user.name = munge
munge.user.uid = 994
slurm.hpc = true
slurm.user.gid = 11100
slurm.user.name = slurm
slurm.user.uid = 11100
```

Cyclecloudの管理サーバーUI -> masterをクリック -> Edit -> Configuration 欄に上記設定を入力する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/9b1eb60e-337b-c109-7e6f-80a2d618960a.png)

最初から入力されている設定を可能な限り残しつつ、重複するものは消して上記設定を入力しました。

## 結果
無事にDSVMを使用したslurmクラスターのデプロイができました！

## 参考
- https://docs.microsoft.com/en-us/azure/cyclecloud/slurm?view=cyclecloud-7#uid-conflicts-for-slurm-and-munge-users
Macに最初から入っているPHPではintlモジュールが有効化されていないくて少し詰まった話

# TL;DR
- Macのローカル環境でPHPUnit走らせるぜー
    - PHP Fatal error: You must enable the intl extension と怒られた
- intlモジュールはPHP5.3.0以降のPHPに同梱されているので有効化すればok
    - https://www.php.net/manual/ja/intl.installation.php
    - MacデフォルトのPHPではintlモジュールは有効化されていない
        - ``` php -m|grep intl ``` で確認した
- HomebrewのPHPはintlモジュールが有効化されている状態でインストールされるとのこと。今回はこちらを使用することにした
    - ``` brew search php ``` で確認。php@7.4があるのでそちらをインストールする
    - 余談。Homebrew版PHPのバージョン切り替えは ``` brew link php@7.x ```でできます

# Homebrew版PHPのインストール

## インストール

```
brew install php@7.4
```


## インストールしたPHPを利用可能な状態にする

- インストールしたPHPへリンクを張る
    - Homebrewでインストールしたバイナリへのリンクは ``` brew --prefix ``` 以下のbinディレクトリに作成されます

```
brew link --force php@7.4
# --forceを付けないとエラーがでます
# 余談。複数PHPをインストールし、unlink→link --overwriteすると一部エラーが出ますがまだちゃんと追っていないです
```

- brew link時に必要に応じてPATHを通すためのコマンドを教えてくれます
    - $SHELLによってbash/zsh用コマンドを出し分けているらしい？親切

```
If you need to have this software first in your PATH instead consider running:
  echo 'export PATH="/usr/local/opt/php@7.4/bin:$PATH"' >> ~/.zshrc
  echo 'export PATH="/usr/local/opt/php@7.4/sbin:$PATH"' >> ~/.zshrc
```

## 確認

- PHP

```
% php -v
PHP 7.4.7 (cli) (built: Jun 12 2020 00:04:10) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.7, Copyright (c), by Zend Technologies
```

- intl

```
% php -m | grep intl
intl
```

めでたしめでたし
KiCad においてポリゴン図形のフットプリントを作成する

#1. はじめに
　KiCad[^1](5.1.6)-1において、少々入り組んだ形のフットプリントを作成する方法を勉強しました。別件で試行錯誤[^2]した際の副産物です。応用としては、導電ゴムを使用した押しボタンスイッチ(ラバーコンタクトスイッチ)の受け側のプリント基板パターンが思いつきます。
[^1]: [KiCad](https://kicad-pcb.org/)
[^2]: [Qiita「KiCadにおいて複数の部品からなるフットプリントを作成する」](https://qiita.com/BotanicFields/items/c3783561dc5fbd6a5d19)
![poli.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/febcb06c-27db-1836-afe9-cefe7d411f5f.png)


#2. フットプリントエディタ
　KiCad は、プリント基板を設計するための高機能な CAD ソフトウェアで、誰でも無料で使うことができます。プリント基板上に部品などを配置する際に使用する図形データをフットプリントと呼びます。KiCad には予め数多くのフットプリントがライブラリとして用意されています。必要なフットプリントがライブラリにない場合、自分でフットプリントを作成や修正するためのフットプリントエディタが用意されています。フットプリントエディタの操作方法やライブラリの管理方法については、解説本[^3]などを参照ください。
[^3]: [「KiCad Basics for 5.x」マッハ新書](https://booth.pm/ja/items/941963)

#3. ヒント
　フットプリントライブラリにヒントがあります。以下のフットプリントには5角形があります。
![poli1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/d478c32d-eee5-3d18-9fb7-e0d0766f9bc5.png)

　パッドのプロパティをみると、カスタム形状(矩形アンカー)とあります。
![poli2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/4253b690-97d7-27a9-1e61-e750b9195626.png)

　「カスタム形状の基本要素」をみると、ポリゴンで角の数が5とあります。
![poli3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/dbe4ccac-3983-31e4-2264-edc9e72b222e.png)

　「基本要素を編集」で「基本形状ポリゴン」を見ることができます。5角形の頂点5個の座標を指定しています。パッドの基準点(0,0)は 5角形の内部にあります。欄外に「塗りつぶしポリゴンにするには太さに０を設定する。」と説明があります。
![poli4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/fee27c05-37a7-a7c6-2378-ed51c43f8ee7.png)

#4. ポリゴン図形の入力
　導電ゴムによるコンタクトを想像して、仮にポリゴン図形を作成してみます。
![poli5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/098ab0fb-da6f-2f44-80c4-ee7f6eee8e29.png)

　矩形アンカーの(0,0)を基点とした図形になりました。
![poli6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/662a062d-8773-02c0-8ea5-f72cd829b52c.png)

　ハンダペースト(F.Paste)、レジストマスク(F.Mask)のチェックを外しています。コンタクトのパッド部分のレジストを除外するために後でレジストマスクを追加します。
![poli7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/079df56f-83b7-c159-57d2-adc41c7a00aa.png)

　作成したパッドをコピーし 180度回転させ向い合せます。
![poli8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/64d5316d-45d3-1ca7-2a7a-c6564aa63fc6.png)

　パッド番号を修正して、レジストマスクを追加して完成です。
![poli9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378410/db271aeb-2709-9e97-d127-ec067bebe1e4.png)

#5. おわりに
　作成したフットプリントは仮のもので、実際の導電ゴムボタンの大きさに合わせて適切に設計する必要があります。このような手作業でも可能な範囲でフットプリントを作成できることがわかりました。
Python初心者がクイックソートを整理する

###これは備忘録です
ホントに忘れそう
#引用サイト
今回は先に整理するために拝見させていただいたサイトを紹介させていただきます

- [アルゴリズム参考](https://qiita.com/muijp/items/257e8b9b49d891137d56)
- [トレース参考](https://www.suzu6.net/posts/68-quicksort/)

それぞれ少しだけアルゴリズム自体が違いますが同じクイックソートなので@muijpさんのアルゴリズムを元に整理させていただきます

#プログラム
[@muijpさんのクイックソート](https://qiita.com/muijp/items/257e8b9b49d891137d56#%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%BD%E3%83%BC%E3%83%88-quick-sort)に先日@shiracamusさんからアドバイスをいただいたランダム配列のプログラムとデバッグ用の出力を入れました

```q_sort.py
def qSort(a):
    print(a)#デバッグ用
    if len(a) in (0, 1):
        return a

    p = a[-1]
    l = [x for x in a[:-1] if x <= p]
    r = [x for x in a[:-1] if x >  p]

    return qSort(l) + [p] + qSort(r)
a = r.sample(range(1,11),k=9)
qSort(a)
#出力＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿
[3, 7, 1, 6, 9, 8, 2, 10, 4]
[3, 1, 2]
[1]
[3]
[7, 6, 9, 8, 10]
[7, 6, 9, 8]
[7, 6]
[]
[7]
[9]
[]
>>[1, 2, 3, 4, 6, 7, 8, 9, 10]
```

うん、プログラムが簡潔すぎて分からない。

#分解して考える
まず注目するべきところは
`return qSort(l) + [p] + qSort(r)`
だと思う。
コレはクイックソートの特徴である「ピポット(注目しているセル)」の右と左に小さい数字(配列)と大きい数字(配列)を置く、という部分になる。　　　　

[トレース参考](https://www.suzu6.net/posts/68-quicksort/)
このサイトのgifを見ていくと
1. 真ん中ピポットを取る
2. 外側から順に左にある小さい数と右にある大きい数を交換する
3. 走査範囲を最小～ピポットに変え、中央にピポットを持ってくる
を繰り返してるのがわかる。

　　
　　
ただ、今回のプログラムでは
`p = a[-1]`
として、ピポットを最後の数に取っている
そして、
    `l = [x for x in a[:-1] if x <= p]`
    `r = [x for x in a[:-1] if x >  p]`
で、ピポットより大きい数字とピポットより小さい数字に分け、それを`return`で(再起関数を呼びつつ)接合している。
　　
　　

最初の
`if len(a) in (0, 1):
        return a`
は文字が1文字以下ならそれを再起関数の返り値として返している。

#トレースし直す
以上を踏まえて先ほどの乱数でトレースしてみる

```
#出力＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿
[3, 7, 1, 6, 9, 8, 2, 10, 4]
[3, 1, 2]
[1]
[3]
[7, 6, 9, 8, 10]
[7, 6, 9, 8]
[7, 6]
[]
[7]
[9]
[]
>>[1, 2, 3, 4, 6, 7, 8, 9, 10]
```
配列[3, 7, 1, 6, 9, 8, 2, 10, 4]
ピポット p　＝　4
小さい配列ｌ　＝｛３，１，２｝
大きい配列ｒ　＝｛７，６，９，８，１０｝
と分解する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650016/7a1cc2ce-dd1e-905a-d49e-3d85a9a58d60.png)

小さい配列を再起し、
p=2
l={1}、r={3}
と分解
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650016/a8973f60-8322-a958-16bd-234036ad3cc5.png)
それぞれ1つまで分解されたので確定する

大きい配列を再起すると、今度のpは10で最大なので、
l={7,6,9,8} 、r={}
と分解される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650016/79ab5e44-c6fd-3089-eb9b-64400b58ed99.png)
その後すべての数を細分化していき
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650016/1d413fe6-11e2-3eb4-8b05-8d4b46f6bbb8.png)
結合されたデータで返される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650016/ae4c7879-f766-6fd5-a314-b7493d045a66.png)
と、なってます。

#さいごに
今回はほぼ丸パクリとなってしまいましたが、いかに自分が理解してないのかがわかってしましました。
このような機会があって本当に良かったです。
EC2におけるwebサーバー構築作法と考え方【概念編】

# イントロ
webサーバー構築するとき、Qiitaで検索しますよね。初心者の方はコマンドを理解せずにコピペしている人もいるんじゃないでしょうか？自分もそうでした。

「なんかよくわかんないけど動くたぞ」、「記事通りにやったのにうまくできなかった」、こんな風にコマンドを理解せずにインフラ構築してました。このままだといつまで経っても自信を持ってインフラ構築できません。

そこで、EC2におけるwebサーバー構築の考え方と作法をお伝えしようと思います。

# 伝えたいこと
- webサーバー構築における、パッケージインストールの３つの手段と、その使い方
    - パッケージ管理ツールを使う方法
    - amazon-linux-extrasを使う方法
    - 外部リポジトリを使う方法
    
#パッケージインストールの３つの方法と使い所
早速説明していきます。
ここはざっくり理解できればいいです。
【実践編】を用意したので、そこで理解を深めてください。
## パッケージ管理ツールを使う方法
### パッケージ管理ツールとは何か？
パッケージをインストールしやすくしてくれる便利ツール。

依存関係の解決もやってくれるので、とても便利。

代表例として、yumがある。EC2でも使えます。

### 使い所
何かをインストールしたい時。

さっき３つのインストール方法があると言ったが、真っ先にこいつを使うことを考えた方が良いです。

## amazon-linux-extrasを使う方法
### amazon-linux-extrasとは何か？
Amazonが公式サポートした新バージョンをyumで扱えるようにする仕組み

### 使い所
yumで確認したバージョンのパッケージよりも、新しいバージョンのパッケージを使いたい時。

## 外部リポジトリを使う方法
### リポジトリとは？
リポジトリとは、パッケージが置かれた場所。

### 外部リポジトリを使う方法とは何か？
ここを理解するには、パッケージインストールの仕組みを理解する必要があります。

パッケージ管理ツールでインストールする時に、例えば、yumならば、

```
yum install パッケージ名
```

でパッケージをインストールできます。

このパッケージはどこからインストールされるのでしょう？

勘の良い方はお気づきかもしれませんが、EC2に登録されたyumリポジトリからインストールされるのですね。

つまり、欲しいパッケージが入っているyumリポジトリが登録されていなければ、yumでインストールできません。

だから、欲しいパッケージを上記コマンドでインストールできない場合は、欲しいリポジトリが入ったyumリポジトリをEC2に登録しなければいけないわけです。

### 使い所
既存のyumリポジトリにも入ってない上に、amazon-linux-extrasでもインストールできないパッケージをインストールしたい時。

# まとめ
実践編も書こうと思ったのですが、実践編も入れると長くなってしまうので、実践編は別の記事で書こうと思います。
というわけでまとめです。

この記事で覚えて欲しいのは、
EC2におけるパッケージインストールの３つの方法とその使い分けです。

- パッケージインストールの３つの方法
    - パッケージ管理ツールでインストール
        - とりあえずこれでインストールできないか考える
    - amazon-linux-extrasを使ってインストール
        - 上の方法でインストールできない場合に検討する
    - 外部リポジトリを使ってインストール
        - 上2つの方法でインストールできない場合に検討する

要するに簡単な方法から検討していこう、ってことです。


実践編ではパッケージインストールの３つの方法を駆使して、webサーバー構築に必要なミドルウェアをインストールしていこうと思います。
この辺の考え方は手を動かさないと身につかないので、ぜひ実践編も読んで、一緒に手を動かしていきましょう。

## 実践編
実践編①：[EC2におけるwebサーバー構築作法と考え方【実践編①】](https://qiita.com/yt_kg/items/1c21227bbebfb62acd09)
データサイエンス100本ノックをColaboratoryでやりたい

データ分析の練習コンテンツ[「データサイエンス100本ノック（構造化データ加工編）」](https://digitalpr.jp/r/39499)がデータサイエンティスト協会から公開されました。
動かすにはDockerの操作が必要なので、手軽に始めて見たい方向けにColaboratoryで動かす方法を残しておきます。
## 1.データをダウンロードする
まずは適当なノートブックを作成してColaboratoryを開きましょう。
開いたら以下のコマンドを実行して、GoogleDrive上にデータをダウンロードします。

```python
from google.colab import drive
drive.mount('/content/drive')

!git clone https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess.git 'drive/My Drive/100knocks-preprocess'
```
ドライブのマウントを初めて実行する方は、実行したセルの下に以下の表示が現れます。URLをクリックしてGoogleColaboratoryのDriveに対するアクセスを許可しましょう。
<img width="620" alt="スクリーンショット 2020-06-17 9.45.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112604/42691a5e-287a-357d-0a05-00fd74b09a26.png">
最後に「このコードをコピーし、アプリケーションに切り替えて貼り付けてください。」と表示されるので、コピーしたコードを上記の「Enter your authorization code:」欄に貼り付けて実行しましょう。
マイドライブに戻ると「100knocks-preprocess」というフォルダが確認できると思います。
うまくいったら、このnotebookはもう使いません。

## 2.マイドライブからJupyter Notebookを開く
notebookファイルは以下のディレクトリに格納されています。
<img width="742" alt="スクリーンショット 2020-06-17 10.04.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112604/bc3f02fb-6d7e-e1d4-d4a4-28005357bdd6.png">
preprocess_knock_Python.ipynb をGoogleColabratoryで開いてみましょう。

##3.動かしてみる
最初のセルをそのまま実行するとエラーになるので、ライブラリのインポートだけを実行したら以下のコードでデータを読み込みましょう

```python
def get_df(filename):
  path = 'drive/My Drive/100knocks-preprocess/docker/work/data'
  return pd.read_csv(os.path.join(path, filename))

df_customer = get_df('customer.csv')
df_category = get_df('category.csv')
df_geocode = get_df('geocode.csv')
df_product = get_df('product.csv')
df_receipt = get_df('receipt.csv')
df_store = get_df('store.csv')
```
ちなみに、以下のフォルダ配下にこのコンテンツの狙いなどを説明したpdfファイルがあるので、取り組む前に読んでみると良さそうですね。
```100knocks-preprocess/docker/dock```

これで準備は完了です
時間を空けて実行するとDriveとの接続が切れてしまう事があるかもしれません。（ないかも...）その場合は再度以下のコードを実行するか、サイドバーからドライブをマウントして改めてデータを読み込みましょう。

```python
from google.colab import drive
drive.mount('/content/drive')
```
###以上
この記事を書いておいてなんですが、Dockerでの環境構築もそんなに難しくないですし、できると役立つことも多いので、これを機会にチャレンジするのもいいと思います。Macでの構築方法は[こちら](https://qiita.com/karaage0703/items/1b18b1f4ab65d35afb5f)の記事が良さそうです。環境が作れればSQLの練習もできますしね！
【github】Files changedにNo changesファイルが存在する時の対処法

## はじめに
プルリクエスト中のmasterブランチとの差分ファイルはFiles changedに表示されます。
このFiles changedにNo changesファイルが存在する際の対処法を書きたいと思います。
(差分がないのに差分ファイルに含まれる→けど差分ないよ！といわれることです)

## なぜ起こったのか？
原因：ローカルとサーバー両方でpushしてしまったから

コードをphpstormで同期していた私はローカル(Mac)、サーバーどちらでpushしても同じものだと思っていました。
なのでbranch1をローカルでpush→masterにマージし、その後にbranch2をサーバーでpushしプルリクエストを出したところ
Files changedタブにNo changesファイルが9つ表示されました。。。

## 対処法
#### 対処法1
masterブランチをpullしてみる
##### 結果
変わらず。。

#### 対処法2
カレントブランチのNo changesファイルを削除しmasterブランチのファイルを落としてくる
##### 結果
File changedにNo changesファイルが出力されなくなった！！！


## まとめ
無理やりmasterブランチのファイルを落とす方法を取りました。
スマートではないので非推奨です。。
【超初学者向け】画面遷移と値の引き渡しをコードで同時に行う。

##はじめに
本記事は、筆者が備忘録として作成したものである。
また同時に超初学者向けの簡単な内容となっております。

##実装したいこと
今回は、Swift学習の超基本である、下記2点について記述する。
①任意のタイミングでの画面遷移
②値の引き渡し(画面遷移と同時に処理)

今回は、ViewContorollerのラベルデータを→NextViewController(遷移先)のラベルへ反映させたいと思います。

##必要なコード
必要なコードは下記のみ

①「任意のタイミングでの画面遷移」

```php:ViewController
//ボタンがタップされた時に画面を遷移する場合。
@IBAction func tapButton(_ sender: Any) { 

performSegue(withIdentifier: "遷移先と繋がるSegueのidentifier", sender: nil)

}
```

②「任意のタイミングでの画面遷移」

```php:ViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

let nextVC = segue.destination as? NextViewController //←遷移先名：NextViewController
nextVC?.NextViewLabel = Labal.text! //ラベル(Label.text)に入っているデータを遷移先のラベル(NextViewLabel:String型)へ引き渡す。

}
```

③遷移先での処理

```php:NextViewController

let NextViewLabel = String() //String型で受け取る。
NextLabel.text = NextViewLabel //　textに表示。
```

以上で完成です。

##結果
画面遷移と値の受け渡しが任意のタイミングで出来る。
Android Studioでエミュレーターが起動しない時の対処法

#初回エミュレーター起動時のエラー
Android studioを使って初めてエミュレーターを起動する際に、エラーを吐かれたので、参考にしてみてください。
いくつかの原因と参考にしたURL・解決策をまとめています。
環境は、windows10です。
また、PCの初期設定でユーザーフォルダ名を全角漢字にしてしまっています。
同じ状態の方には参考になるかもしれません。
##エラー対処
`Emulator: PANIC: Cannot find AVD system path. Please define ANDROID_SDK_ROOT
Emulator: Process finished with exit code 1`

これは、ANDROID_SDK_ROOTが見つからないのでAVDが動かせませんよ～と言われています。
ひとまずは、環境変数の設定をします。
環境変数の設定は、

[左下の検索バー]→[コントロールパネル]→[システムとセキュリティ]→[システム]
→[左端にあるシステムの詳細設定]

で設定することができます。
そこで変数名をANDROID_SDK_ROOTにして、値をSdkフォルダがある場所に指定してあげます。
StackOverFlowで結構記事が見つかるので、英語ですが参考にしてみてください。
[参考記事](https://stackoverflow.com/questions/48510124/panic-cannot-find-avd-system-path-please-define-android-sdk-root-in-windows-1)

しかし、僕の場合はこれでは動きませんでした。
そこで以下の記事を参考にしてみました。
[Stack Over Flow](https://stackoverflow.com/questions/39645178/panic-broken-avd-system-path-check-your-android-sdk-root-value/44386974#44386974)

この記事の1つ目の方法で解決しました。
やり方は、
ユーザーフォルダ内にある`.android`というフォルダをパスが通るフォルダに移動させます。
僕は、C直下に`Folder`というファイルを作ってその中に.andoridを移しました。
その後、環境変数に`ANDROID_SDK_HOME`という変数で値をANDROID_SDK_ROOTと同じところにして設定します。

すると、エミュレーターが無事に起動しました。
先ほど紹介した記事では、他の原因についても言及してあるのでいずれかには当てはまると思います。
記事に紹介してある原因を簡単にまとめると、

・Sdkフォルダが破損しているかもしれないから、一度フォルダに必要なものが揃っているか照らし合わせてみてよ。

・必要なパッケージが揃っているか調べてみてくれ。ひとまず下の3つは必要だ。
emulator (Android Emulator)
platform-tools (Android SDK Platform-Tools)
tools (Android SDK Tools)
これがあれば、HAXMがインストールされてないかもしれないから、インストールしてくれ。

・4つ目はよく分からないからスルーで。笑

#エミュレーターを起動する際のトラブルシューティング記事まとめ
最後に結構いろんなトラブルシューティングの記事を見てきたので、ザっとご紹介します。

[【Android Studio】AVD(Android Virtual Device)が起動しない場合の対処法](http://webstation.work/?p=184)
[Android エミュレータで「Error while waiting for device:…」がでた時](http://www.aqlier.com/2018/12/28/android-haxm/)
[Android Studioでエミュレータを起動しようとするとエラー「PANIC: Cannot find AVD system path. 」が表示される。](https://teratail.com/questions/236365)
【覚書】Windows環境でOpenCVチュートリアル（顔認識）をやってみた話

検索系の相談で、図面を全文検索できないかといった相談があり
実現確度の検証のためにOpenCVのチュートリアルをやってみた。

以下は自分が行った手順の覚書です

**前提**
OS：　
　Windows10 64bit

Python：
　Python3.7(Anaconda3)


**目標**
　OpenCV環境の構築から、簡単なチュートリアル実施まで（とりあえず顔認識くらいまでは実施したい）



# 準備

## アナコンダのインストール

https://www.anaconda.com/products/individual

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/b1fa2f95-22c1-6a6b-2f4a-eb845dcb7637.png)




## OpenCVのwhlをダウンロード

https://opencv.org/releases/

・上のタブからRELEASESをクリック。
・OpenCV – 4.2.0のSourcesをクリック
・zipを解凍して、opencv_python‑4.2.0‑cp37‑cp37m‑win_amd64.whlを取り出す
※Githubから取得したファイルは、2020/06時点でエラーとなるため公式から取得したファイルを使用しました


## アナコンダのナビゲータでOpenCV環境を作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/7039ef28-94d9-6bc7-5fae-69c89dc68f5f.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/8a766be2-4c79-fae1-4ef4-b4adb775c38d.png)


## numpy と matplotlib をインストール


```console
conda install numpy
```

```console
pip install matplotlib
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/148eb71b-6798-dff6-a014-9f3fc277f212.png)


★ここまでに参考にした記事
基礎構築時に参考にした記事
https://qiita.com/FukuharaYohei/items/5d49938ffd33d198f0c0

CascadeClassifierエラーの対策の為に参考にした記事
http://sh0122.hatenadiary.jp/entry/2017/10/30/210411



# チュートリアル

お試し的にやってみるので、まずは顔認識をしてみようと思います。
基礎が理解できればあとは基礎をカスタマイズしていくだけです。

## カスケードファイルの取得
分類や認識に必要な特徴量をすでに学習済みデータが集約されたxmlファイルです
今回は顔認識の為に『haarcascade_frontalface_default.xml』を使用
https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml


## 顔認識に使用する写真

今回使用する写真はSNOWで可愛く加工した自分の写真です。　
これ認識できるのか・・・？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/284dd969-58e8-592c-e6e7-62726866faea.png)


## pythonコードをかいてみる test.pyという名前で以下の処理を書きます

```python
import cv2

# 分類器
cascadeFile = "C:\imagepy\haarcascade_frontalface_default.xml"

# 分類器の設定
cascade = cv2.CascadeClassifier(cascadeFile)

# 入力ファイル
imageImput ="C:\imagepy\myface.jpg"

# 入力ファイルをリードする
image = cv2.imread(imageImput)

#グレースケールにする
imageGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 出力ファイル
imageOutput = "C:\imagepy\out.jpg"

# 顔を認識する
facerect = cascade.detectMultiScale(imageGray, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))

# 顔を検出できた際の処理
if len(facerect) > 0:

    # 顔に枠を付ける
    for rect in facerect:
        cv2.rectangle(image, tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]), (255, 255, 255), thickness=2)

    # 結果を画像として保存する
    cv2.imwrite(imageOutput, image)
```



## test.pyを実行してみます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/12144a79-7c36-730f-746f-a26591ab0f86.png)



SNOWで可愛く加工した自分の写真でも顔として認識されているようです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/dc622056-0b91-fe4d-77b9-80b0478ee760.png)



今回の目標であるチュートリアルの実施までは完了しました。
次回は図面上にある記号やオブジェクトを認識して、全文検索可能にするといったことをやってみたいと思います。

仕事で使う図面で試験するわけにはいかないので地図内の記号を認識して、全文検索可能な状態を目指すかなー。。。