OmniAICreator/Qiita-1.07M huggingface dataset:
Ionicで検索機能を実装する

#はじめに
ionicでの検索機能を実装したので紹介します。
[ion-searchbar](https://ionicframework.com/docs/api/searchbar)を使って実装します。
以下のような検索機能が実装できます。
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/c57f1b1b-d647-6451-8b46-14be250c4f82.gif)


#プロジェクトを作成する
```
ionic start searchBar blank --type=angular
```

#検索機能を実装する
```/src/app/home/home.page.html
<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>
      検索
    </ion-title>
  </ion-toolbar>
  <ion-toolbar>
    <ion-searchbar 
      showCancelButton="focus"
      placeholder="入力してください"
      (ionInput)="getItems($event)">
    </ion-searchbar>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-list>
    <ion-item *ngFor="let item of itemList">
      <ion-label>
        {{item}}
      </ion-label>
    </ion-item>
  </ion-list>
</ion-content>
```

```/src/app/home/home.page.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {
  itemList = [];
  constructor() {}

  ionViewWillEnter() {
    this.itemList = ['Amsterdam', 'Bogota', 'Buenos Aires', 'Cairo', 'Dhaka',
              'Edinburgh', 'Geneva', 'Genoa', 'Glasgow', 'Hanoi', 'Hong Kong',
              'Islamabad', 'Istanbul', 'Jakarta', 'Kiel', 'Kyoto', 'Le Havre',
              'Lebanon', 'Lhasa', 'Lima', 'London', 'Los Angeles', 'Madrid',
              'Manila', 'New York', 'Olympia', 'Oslo', 'Panama City', 'Peking',
              'Philadelphia', 'San Francisco', 'Seoul', 'Taipeh', 'Tel Aviv',
              'Tokio', 'Uelzen', 'Washington'];
  }

  async getItems(ev: any) {
    let value = ev.target.value;
    if (value === '') {
      this.itemList = ['Amsterdam', 'Bogota', 'Buenos Aires', 'Cairo', 'Dhaka',
      'Edinburgh', 'Geneva', 'Genoa', 'Glasgow', 'Hanoi', 'Hong Kong',
      'Islamabad', 'Istanbul', 'Jakarta', 'Kiel', 'Kyoto', 'Le Havre',
      'Lebanon', 'Lhasa', 'Lima', 'London', 'Los Angeles', 'Madrid',
      'Manila', 'New York', 'Olympia', 'Oslo', 'Panama City', 'Peking',
      'Philadelphia', 'San Francisco', 'Seoul', 'Taipeh', 'Tel Aviv',
      'Tokio', 'Uelzen', 'Washington'];
    }
    // if the value is an empty string don't filter the items
    if (value !== '') {
      this.itemList = this.itemList.filter((item) => {
        //前方一致
        if (value.match(/^[A-Za-z0-9]*$/)) {
          return (item.toString().toLowerCase().indexOf(value.toLowerCase()) === 0);
        } else {
          return (item.toString().toLowerCase().indexOf(value.toLowerCase()) === 0);
        }
        //部分一致
        /*
        if (value.match(/^[A-Za-z0-9]*$/)) {
          return (item.toLowerCase().indexOf(value));
        } else {
          return (item.toLowerCase().indexOf(value));
        }
        */
      });
    }
  }
}
```

#おわりに
[ion-searchbarのページ](https://ionicframework.com/docs/api/searchbar)では部分一致検索が紹介されていましたが、今回は前方一致検索を実装してみました。
ActiveRecord::Migration is not supportedの時

#原因
StandardError: Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Rails release the migration was written for:

#対処法
新しく生成されたMigrationファイルにバージョンをつける、下記例：

```xxx_add_attachment_image_to_photos.rb
class AddAttachmentImageToPhotos < ActiveRecord::Migration[5.2]
```
お気に入りpythonモジュール達やバイナリを１つのLambda Layerにまとめるスクリプト

LambdaとLayersは便利ですが、１つの関数につき上限は５つまでと制限があります。
Layersは＝１モジュールとして運用しているケースが多いかと思いますが、意外と足りなくなったり１つずつ追加するのは手間です。
お気に入りのモジュールたちはお馴染みの`requirement.txt`で管理し、１つのレイヤーにまとめてしまいましょう。

テストで６つのモジュールをインポートする[requirement.txt](https://github.com/umihico/squeezed-python-lambda-layer/blob/master/requirements.txt)を作成します。

```bash:requirement.txt
selenium
requests
Pillow
lxml
numpy
Flask
```

そして同階層にて以下の[スクリプト](https://github.com/umihico/squeezed-python-lambda-layer/blob/master/publish_layer.sh)を実行します。dockerの
pythonのバージョンや、awsコマンドの引数は必要に応じて編集してください。

```bash
mkdir -p python/bin/
docker run --rm -v $(pwd):/var/task -w /var/task lambci/lambda:build-python3.7 pip install -r requirements.txt -t ./python
zip -r layer.zip python
aws lambda publish-layer-version --layer-name favorites --zip-file fileb://layer.zip --compatible-runtimes python3.7 --region ap-northeast-1
rm -rf layer.zip python
```

Lambdaに登録されたレイヤーを追加できるようになりました。テスト関数は[このレポジトリから](https://github.com/umihico/squeezed-python-lambda-layer)Serverless Frameworkによるデプロイ・確認を行いました。以上です！

Serverless Frameworkを使うなら[serverless-python-requirements](https://www.npmjs.com/package/serverless-python-requirements)を使えばモジュール管理は楽になりますし、レイヤーを使って分離しない方がInfrastructure as Codeの徹底がされていてエレガントだと思います。しかしレイヤー数の上限が障害になったり、モジュールがパッケージに含まれるとデプロイの待ち時間が長くなるので、個人的にはレイヤーで分離するほうが小回りが聞いて好みです。 

ちなみにseleniumを使うならバイナリも一緒にあげて管理すると楽です。以下がバイナリも追加する[スクリプト](https://github.com/umihico/squeezed-python-lambda-layer/blob/master/publish_selenium_layer.sh)です。
余談ですが、私が把握しているlambdaでpythonで動くheadlessなseleniumはこのスクリプトのバージョンとpython3.7のセットです。古いリリースのバージョンを使っているのはそのためです。

```diff
mkdir -p python/bin/
+ curl -SL https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-37/stable-+ headless-chromium-amazonlinux-2017-03.zip > headless-chromium.zip
+ unzip headless-chromium.zip -d python/bin/
+ curl -SL https://chromedriver.storage.googleapis.com/2.37/chromedriver_linux64.zip > chromedriver.zip
+ unzip chromedriver.zip -d python/bin/
+ rm -rf chromedriver.zip headless-chromium.zip
docker run --rm -v $(pwd):/var/task -w /var/task lambci/lambda:build-python3.7 pip install selenium -t ./python
zip -r layer.zip python
aws lambda publish-layer-version --layer-name selenium_with_bin --zip-file fileb://layer.zip --compatible-runtimes python3.7 --region ap-northeast-1
rm -rf layer.zip python
```

seleniumがlambda上で正しく動くためのchromeOptionsやこのレイヤーから得るバイナリのパスを設定したテスト関数は[こちら](https://github.com/umihico/squeezed-python-lambda-layer/blob/master/scraping.py)です。

参考
https://github.com/adieuadieu/serverless-chrome/issues/133
https://dev.classmethod.jp/articles/managing-external-modules-with-serverless-framework-plugin/
https://www.npmjs.com/package/serverless-python-requirements
https://hacknote.jp/archives/49974/
https://dev.classmethod.jp/articles/lambda-layer-first-action/
「App Extensions」（iOSアプリケーションの拡張）で「Core Data」を使用する

## 「App Extension」とは？
[App extensions](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/index.html) は、主要iOSアプリケーションの拡張機能です。例えば、「iMessage Extension」、「Today Extension」、「Siri Extension」などがあります。

<img width="743" alt="Screen Shot 2020-05-12 at 3.38.39 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/bfba1ff6-8b52-9de7-71ba-79141a559e14.png">

##「Core Data」とは？
[Core Data](https://developer.apple.com/documentation/coredata) はAppleのフレームワークであり、ユーザー情報をローカルストレージに格納するのに便利です。また、CloudKitのサポートも組み込まれており、ユーザーたちのすべてのデバイスで変更内容を同期できます。

## 本日のトピック?
Core Data には、次のコードを使用することで、主要iOSアプリで簡単にアクセスできます：

```swift
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
```

ただし、App Extensionからもアクセスできるようにするには、いくつかの追加の手順を行う必要があります。

:bangbang: 警告：この変更は、既存のアプリを更新する時にではなく、未公開のアプリを最初に開発する段階で行ってください。

## 複数のApp ExtensionにわたるCore data

### 1. App Group を有効にする
最初に「Signing & Capabilities」タブに進み、「+」アイコンを選択します。

<img width="951" alt="Screen Shot 2020-05-12 at 3.53.18 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/5a112af5-af64-e02f-e250-50e83c433eaa.png">

主要iOSアプリとその他のすべてのターゲット向けに「[App Group](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups)」を追加します。

すべてのターゲットに同じ「App Group」を割り当てます。

<img width="939" alt="Screen Shot 2020-05-12 at 3.55.43 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/d9d631cc-a00f-00b5-1b3a-c275d47693f1.png">

### 2. ヘルパーを追加

まずファイル「*. xcdatamodel」を探します。ファイル名が「Sakura.xcdatamodel」の場合、データベース名が「Sakura」ということです。

```swift
import Foundation
import CoreData

class NSCustomPersistentContainer: NSPersistentCloudKitContainer {
    
    override open class func defaultDirectoryURL() -> URL {
        var storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.[App Group Name 名前]")
        storeURL = storeURL?.appendingPathComponent("Sakura.sqlite")
        return storeURL!
    }

}

```

### 3. データベースにアクセスする

これで次の方法でデータベースにアクセスできるようになりました：

```swift
lazy var persistentContainer: NSPersistentContainer = {
        let container = NSCustomPersistentContainer(name: "Sakura")
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                print(error.localizedDescription)
            }
        })
        return container
    }()

let context = persistentContainer.viewContext
```

### この記事は、複数の拡張機能にわたるデータベースのサポートを新規アプリ向けに追加するためのものです。ユーザーストレージにデータがある場合、アプリのデータを常に復旧できるようにするために、重要な変更を行う前は必ず別途バックアップを取っておくようにしてください。

---

:relaxed: [Twitter @MszPro](https://twitter.com/MszPro)

:sunny: [私の公開されているQiita記事のリストをカテゴリー別にご覧いただけます。](http://mszpro.com/ioskiji/)
<img width="150" src="https://cdn.mszmagic.com/static-web-content/AppClipImage_small.png">
【Firefox】でローカルファイル（file:///）を読み込んだ時にCORSエラーを出ないようにする

# TL;DR;

以下の手順で、開いたHTMLの親ディレクトリ配下のファイルはCORS制限を受けなくなります。

1. `about:config` を開く
2. `privacy.file_unique_origin` をfalseに設定

# CORSについて

あるページで実行されているJavaScriptが、別ドメインのファイルにアクセスしようとしたときにそれを制限する「ブラウザの機能」です。
制限なので、アクセスされる側のサーバーに設定をするなどすることで許可することもできます。また、ブラウザの機能なので、起動オプションや一部のアドオンによっても無効化できるケースがあるようです。

元々は、エンドユーザーのセキュリティというよりは、他のサイトのスクリプトから勝手にコンテンツを盗用されないためのいわば著作権保護的な側面が強かったと聞いたことがあります。

```html:http//example.com/index.html
<!-- 一般的なCORS、回避するにはサーバーの設定が必要 -->
<script>
var xhr = new XMLHttpRequest();
xhr.open( 'GET', 'http://hoge.com/data.hteml' );
xhr.send(); // CORSエラー！
</script>
```

```html:file///c/Users/Admin/Downloads/index.hteml
<!-- 上記設定で回避可能な例 -->
<script>
var xhr = new XMLHttpRequest();
xhr.open( 'GET', 'file:///c/Users/Admin/Downloads/data.hteml' );
xhr.send(); // CORSエラー！同じ「file:///c」だけどダメ。
</script>
```

# 補足と弊害

元々はデフォルトで許可されていたらしいのですが、Firefox68からデフォで制限されるようになったらしいです。
（執筆時点（2020/05/18）では最新が 76）
理由としては「CVE-2019-11730 の対策」とのこと。
この「CVE-2019-11730」ですが、悪意のあるhtmlをダウンロードしてしまいそれをうっかり開いてしまったときに、ダウンロードフォルダの中身が自由にみられてしまうというものです。なので、上記オプションによりこのような攻撃に対して脆弱になっている状態だということは頭に入れておいてください。
（うっかり開いたのがhtmlではなくexeだったらなんでもありですがｗ）

# 参考

* [file: URI の同一オリジンポリシー（MDN）](https://developer.mozilla.org/ja/docs/Archive/Misc_top_level/Same-origin_policy_for_file:_URIs)
* [Reason: CORS request not HTTP（MDN）](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS/Errors/CORSRequestNotHttp)
* [Mozilla Foundation Security Advisory 2019-21（MDN）](https://www.mozilla.org/en-US/security/advisories/mfsa2019-21/#CVE-2019-11730)
* [ローカル(file:///)上で外部ファイル読み込みのセキュリティ制約を回避するいくつかの方法（Qiita）](https://qiita.com/nissuk/items/1ede2953a8661dc59214)
EC2にgit cloneする方法

EC2にコードを展開する時、`git clone`でやると簡単にDeployできます。
なんとなく手順を覚えているものの、ところどころ忘れていることもあるので、やり方をまとめておきます。

- `Amazon Linux 2`でのやり方です。
- リポジトリは、GitLabを使っています。

# SSH Keyの作成

`git clone`を実行するには、`GitLab`とSSHで通信する必要があります。
SSHキー用のディレクトリへ移動し、SSH通信で使用するキーを作成します。

```common-lisp
$ cd ~/.ssh
$ ssh-keygen -t rsa -C "[Gitlabで登録したEmail]"
```

コマンドを実行すると、3つ質問されますが、`Enter`3回でOKです。

```common-lisp
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/(username)/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```

# 作成されたキーに権限を付与
コマンドが正常に完了すると、`id_rsa`, `id_rsa.pub`という2つのファイルができます。
`id_rsa`は、秘密キーという非常に大切なキーなので、適切な権限が付与されている必要があります。

以下のコマンドで、権限を付与します。

```common-lisp
$ sudo chmod 600 id_rsa
```

# GitLabへキーを登録
リポジトリと通信するためには、生成されたキー `id_rsa.pub` をGitLabへ登録し、有効化する必要があります。

　1. `id_rsa.pub`を開き、文字列をコピーします。
　　(`ssh-rsa...`のところから全部コピーします)

```common-lisp
$ cat id_rsa.pub
ssh-rsa AAA....1yc2EAAAADAQABAA........../j21AEwVC1i/+SBcQgTvccQd......
```


　2. Gitlabの`SSH Keys`メニューをクリックし、キーを貼り付け、`Add Key`をクリックします (`SSH Keys`は、User Settingsの中にあります)。
<img width="550" alt="Bildschirmfoto_2020-05-17_um_23_07_27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626057/e5b1180d-6964-8da5-6ca8-9c133edf15a0.png">

# SSH通信の確認
ここまでの設定が完了したら、EC2上でGitLabへの通信を確認します。

```common-lisp
$ ssh -T git@gitlub.com
```
`Welcome to GitLab, @XXXXXX!`と表示されば、通信できています。

# git cloneの実行
以下のコマンドを実行し、リポジトリをCloneします。

```common-lisp
$ git clone git@gitlab.com:XXX/TTT.git
```

これで、GitLabのリポジトリからコードを取得できます。


# もしうまく行かない時は、、、

上記の設定を行っても、`git clone`がうまく行かないことがあります。
こんなエラーが出たり、、、

```
Cloning into 'Project Name'...
Permission denied (publickey).
fatal: Could not read from remote repository.
```

この場合、以下の2つの点を確認してみてください。

1. `git clone` コマンドは、sudoを**つけない**で実行しているか？
 - `sudo` をつけてコマンドを実行すると、rootで実行することになるので、せっかく作成し たキーを利用できていない可能性があります。

2. Cloneしようとしているディレクトリは、`ec2-user:ec2-user` になっているか？
 - ec2-userに書き込み権限がないディレクトリには、`Clone` できないので、そこも意外と盲点だったりします。


<br>
<br>
なんちゃって slack clone

#概要

slack cloneを作ってみた。

#出来る事

- リアルタイム　チャット

#できないこと
- 認証
- チャンネル
- ダイレクトメッセージ
- スレッド
- ワークスペース
- データの永続化

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/73c722b7-427b-bb2f-b893-1e208f282d87.png)


#利用したライブラリー、サービス
## フロントエンド
- plunkerに設置
- フレームワークは、vue
- UIは、tailwind

## 通信
- websocket

## バックエンド
- node-red
- enebularでedit
- herokuに設置

#flow

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c9692835-d6d1-66fb-e2d5-51b0bb06fcc6.png)


#サンプルコード


```

var url = "wss://.herokuapp.com/pub";
var ws = null;
var app = new Vue({
	el: '#app',
	data: function() {
		return {
			id: "",
			message: "",
			messages: [{
				"msg": "message",
				"id": "123",
				"time": "11:46"
			}]
		}
	},
	methods: {
		onMessage: function(e) {
			var json = JSON.parse(e.data);
			this.messages.unshift({
				"msg": json.msg,
				"id": json.id,
				"time": this.getTime()
			});
		},
		onError: function(e) {
			alert("接続に失敗しました。やり直してください。");
		},
		onClose: function(e) {
			//alert("close");
			ws = null;
			setTimeout("app.open()", 3000);
		},
		open: function() {
			if (ws == null)
			{
				ws = new WebSocket(url);
				ws.onopen = this.onOpen;
				ws.onmessage = this.onMessage;
				ws.onclose = this.onClose;
				ws.onerror = this.onError;
			}
		},
		onOpen: function(e) {
			//alert("接続しました。");
		},
		send: function(msg) {
			ws.send(JSON.stringify({
				'msg': msg,
				'id': this.id
			}));
		},
		getUniq: function() {
		  var strong = 10000;
  		return Math.floor(strong * Math.random()).toString(16) 
		},
		keypress: function() {
			if (this.message == "")
			{
				return;
			}
			this.send(this.message);
			this.message = "";
		},
		getTime: function() {
			return new Date().toTimeString();
		}
	},
	mounted: function() {
		this.id = this.getUniq();
		this.open();
	}
});




```


以上。
来場者非接触検温装置 micro:bit+Scratch

#はじめに

　先日、作った「[micro:bitとMLX90614で非接触体温計](https://qiita.com/asondemita/items/0ddafceb2b8b4ac95c20)」。測定結果を音と共にPCのディスプレイに大きく表示する装置をScratchと組み合わせて作ってみました。
![sokutei.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44523/236ba591-2803-4666-4d15-9c4692e58b2b.jpeg)


# 注意事項

あくまでも試作になります。
実際に運用して、誤検出によりクラスターが発生しても責任は取れません。

# 仕様

- 補正
    - 初めにだけ１度行います
    - 予め一般の体温計で自身の体温を測定します
    - センサーを自身の額に当てます（1cm程度離す）
    - micro:bitのBボタンを押すと体温を測定した上で一般の体温計で測った値を質問します
    - 一般の体温計で測った値を入力し、誤差を補正値として記憶します
- 測定
    - センサーを被験者の額に当てます（1cm程度離す）
    - micro:bitのAボタンで測定開始
    - 補正を加えた上で37.5度以上の場合は×。未満の場合は○を効果音と共に表示します。
![体温測定結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44523/c92e9f0a-73ea-9d83-c64e-edf9280849b8.jpeg)

# 仕組み

　Scratch3.0標準のmicro:bit拡張では、I2Cで取得した値をScratchに渡す事が出来ません。そこで、Yengawa Labの[Microbit More](https://lab.yengawa.com/project/scratch-microbit-more/)を使います。
　Micro:bit More にはslotという機能があり、MakeCode上で、独自の計測値をScrachに渡すプログラムを書く事が出来ます。ただ、前回使ったMakeCode用機能拡張 https://github.com/DoraLC/pxt-MLX90614 は、入れようとするとMicrobit Moreが必須としているBluetooth拡張とコンフリクトを起こすようです。対策として今回は、pxt-MLX90614は使わずに直接I2Cを叩きます。
　また、体温を小数点第一位まで表示したかったので、温度を10倍してslotに渡し、Scratch側で1/10にする事にしました。

# 用意する物・配線・ボディ

　[micro:bitとMLX90614で非接触体温計](https://qiita.com/asondemita/items/0ddafceb2b8b4ac95c20)を参照願います。なお、コードレスにしたい場合はmicro:bit用の電池ボックスが必要となります。

# micro:bit側のプログラム

1. [Microbit More](https://lab.yengawa.com/project/scratch-microbit-more/)のファームウェア scratch-microbit-more-0.3.2 をMakeCodeで開きます。
2. MLX90614の値をslot0に書き込むプログラムを作成します。500msの一時停止は無くても動作しますが、長時間運用すると動作が不安定になるケースがあったため入れてみました。
![microbit-画面コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44523/9ec2c060-c64f-f01a-265a-8a53d988623f.png)
https://makecode.microbit.org/_FLie6gTkih9U
3. 作ったプログラムをmicro:bitにダウンロードします。

# Scartch3.0側のプログラム

1. Micro:bit More専用のScratch3.0サイト https://yokobond.github.io/scratch-ext/microbit-more/ にアクセスします
2. Scratch Link（Scratch3.0がmicro:bit拡張用として標準で提供されている物）を起動し micro:bitをBluetoothで接続します。
3. 仕様に従い、以下のようなプログラムを組みます。

![scratch検温.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44523/47a572b7-c41f-2869-a24e-8b9ae64f0da5.jpeg)
https://www.dropbox.com/s/i6tvbktb89mewe2/noncontact_thermometer.sb3

# 動作確認

1. まずは補正を行います
2. 被験者の額に当てて検温を行います

非接触体温計の宿命だと思いますが、実測値はかなりずれる事が判ります。

# おわりに

繰り返しになりますが、あくまでも試作になります。
実際に運用して、誤検出によりクラスターが発生しても責任は取れません。
仮に運用する場合は、自己責任でお願いします。
また、新型コロナウイルスは発熱の無い感染者も多くいるそうなので、測定する事自体がどこまで意味があるかは不明です。
やらないよりやった方がマシという事ですね。
初心者によるプログラミング学習ログ 319日目

#100日チャレンジの319日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
319日目は、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>319日目 5h<br>・ポートフォリオ作成<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1262112767772782593?ref_src=twsrc%5Etfw">May 17, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Dockerの構成とコンテナ生成について

#はじめに
この記事ではDockerの仕組みについて説明します。

##対象
Docker初心者で、Dockerの仕組みを知りたい方向け。
コマンド等具体的な手順、Dockerファイルについて説明していません。
また、かみ砕いた表現をしているため、正確性には欠けているかもしれません。

##参考資料
主に「[15Stepで習得 Dockerから入るKubernetes コンテナ開発からK8s本番運用まで](https://www.amazon.co.jp/15Step%E3%81%A7%E7%BF%92%E5%BE%97-Docker%E3%81%8B%E3%82%89%E5%85%A5%E3%82%8BKubernetes-%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E9%96%8B%E7%99%BA%E3%81%8B%E3%82%89K8s%E6%9C%AC%E7%95%AA%E9%81%8B%E7%94%A8%E3%81%BE%E3%81%A7-StepUp-%E9%81%B8%E6%9B%B8/dp/4865941614)」を参考に書いています。

#1.コンテナとは
Dockerはコンテナ技術の一種です。
Dockerの説明の前に、まずはコンテナについて説明していきます。

コンテナとは、アプリケーションを起動する際に必要なミドルウェア、ライブラリ、設定ファイル等をひとまとめにしたものです。
複数のコンテナがある場合もそれぞれ独立しているため、別のマシンが動いているかのように扱うことができます。
![コンテナと物理マシン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620484/c1f06bb2-bdc5-856b-a392-4d001933203e.png)


コンテナのメリットには以下のようなメリットがあります。
##(1)利用するリソースを削減
以前から仮想環境を構築する方法がありましたがリソースの消費が大きいことが課題でした。
ここでコンテナとの比較のため、従来までの仮想マシンを用いた仮想化環境の説明をします。
仮想マシンを用いた場合以下の構成になります。
![仮想マシンを用いた仮想化環境の構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620484/3333ed0b-31ef-e94e-05d4-8b23a885c639.png)

ゲストOSが必要なためリソース消費が大きくなります。

一方、コンテナは以下の図のように構成されています。
ゲストOSがないためリソースの消費量を削減できます。
![コンテナ構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620484/c5f29c24-da81-7eab-b05d-3b07a52584e9.png)

ハードウェアやCPUの利用率を高めることができ、ハードウェアを効率よく利用することができます。

##(2)アプリケーションを異なる環境へ移行しやすい
コンテナの中には、アプリケーション等を実行するために必要なミドルウェア、ライブラリなどがひとまとめになっています。
例えばローカル環境で動作確認し、商用環境に移行するときもコンテナごと移動できるので、
ローカル環境と商用環境で実行構成を変更することなく移行できます。

##(3)環境の構築、設定のしやすさ
コンテナは環境がコード化されているため、構成管理がしやすくなっています。
同様の環境を作る際には、ファイルをビルドするだけで環境構築できます。

参考リンク
https://knowledge.sakura.ad.jp/13265/

#2.Dockerについて
では本題のDockerについて説明します。
Dockerはコンテナの作成、実行、イメージ管理を支援するツールです。
「Dockerイメージ」とは、読み取り専用のコンテナテンプレートで、
コンテナを起動するための実行形式や設定ファイルのかたまりです。
Dockerの構成は下の図のようになります。
![Dockerの構造 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620484/890afe5d-4348-bef4-1eb1-8afde995943c.png)


矢印(1)～(3)はdocke runコマンドを実行した際の処理の流れになります。

##(1)Dockerコマンドを入力
クライアントはDockerコマンド(コマンドラインユーザーインターフェース)です。
DockerデーモンがDockerコマンドの要求を受け取り、Dockerオブジェクトを管理しています。
この図では「docker run app: 1.0」という要求を受け取り、
イメージ名「app」でタグ名「1.0」がついたイメージからコンテナを生成する処理を実行します。


##(2)レジストリからローカルリポジトリにイメージをコピーする。
Dockerイメージはレジストリに保管されています。
レジストリには以下の3種類あります。
【1】パブリックレジストリ
・Docker Hub
・Quay
誰でも無料で利用できる一般公開されているレジストリです。
docker runコマンドはデフォルトでDocker Hubからイメージをとってくるように指定されています。
参考リンク:https://knowledge.sakura.ad.jp/2210/

【2】クラウドのレジストリ
・Amazon Elastic Container Service
・Azure Container Registry
・Google Container Registry
レジストリの利用者をクラウドのユーザーアカウントに限定することができます。

【3】プライベートレジストリ
・Harbor
・GitLab
・registry
リポジトリ利用者のアクセス元を制限することができます。



レジストリは複数のリポジトリから構成されています。
リポジトリとは、イメージ名にタグをつけてバージョン等を識別して保管しています。



この図ではイメージ名「app」、タグ名「1.0」がついたイメージをレジストリから探し、
ローカルリポジトリにコピーします。

##(3)ローカルレジストリからDockerコンテナを生成
ローカルレジストリに持ってきたイメージ名「app」、タグ名「0.1」のイメージからコンテナを作り出します。
このことを「インスタンス化する」とよく表現されますが、
「イメージ」というひな形からコンテナの「物体」を作り出している、
と想像するとわかりやすいと思います。



これでdocker runの処理は完了し、コンテナが生成されます。
EC2にnginxをセットアップする

EC2にnginxをインストールする方法のメモです。
EC2のインスタンスを立ち上げてからの手順をまとめておこうと思います。
(`Amazon Linux 2023` へのインストール方法です。）

# インスタンスのアップデート
`yum update`を実行し、インスタンスをアップデートします。

```common_lisp
sudo yum update
```

# nginxの`yum`の有効化
EC2インスタンスは、nginxの `yum intstall`が有効になっていなかったので、以下のコマンドで有効化します。
> _2023/4/7現在、Amazon LinuxではNginxのyumインストールが有効となっているので、このコマンドは不要_

```common_lisp
sudo amazon-linux-extras enable nginx1
```

# nginxのインストール
`yum` コマンドでnginxをインストールします。

```common-lisp
sudo yum -y install nginx
```

# インストールの確認
以下のコマンドで、インストールされたバージョンを確認します。

```common-lisp
$ nginx -v
  nginx version: nginx/1.24.0
```

# 自動起動の設定
インストールしただけですと、OSを再起動した際に、nginxが自動で起動してくれないので、自動起動のための設定を行います。

```common-lisp
sudo systemctl enable nginx
```

# nginxの起動
以下のコマンドで、nginxを起動します。

```common-lisp
sudo systemctl start nginx.service
```

# nginxの状態確認
以下のコマンドで、nginxの状態を確認します。正常に起動できていると、ログ中に` Active: active (running)` と表示されます。

```common-lisp
$ sudo systemctl status nginx.service
 nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since So 2020-05-17 19:27:25 UTC; 9s ago
   Process: 847 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
   Process: 844 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
   Process: 843 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
   Main PID: 850 (nginx)
   CGroup: /system.slice/nginx.service
           ├─850 nginx: master process /usr/sbin/nginx
           └─851 nginx: worker process
```

以上で、nginxのセットアップは完了です。

<br>
<br>
VSCode Remote WSLにおけるPATHの設定

VSCode Remote WSL で開発するにあたって，Linuxbrew の PATH の設定が読み込まれておらず，うまくライブラリの連携ができていない問題があったためメモ。


# 統合ターミナルで PATH を設定したいだけの場合
VSCode の統合ターミナルを使うにあたって，PATH の設定をしたいだけの場合，統合ターミナルをログインシェルとして起動すればよい。
具体的には，`settings.json`に以下を追記。

```json:settings.json
"terminal.integrated.shellArgs.linux": [
        "-l"
    ]
```

ログインシェルと別の環境変数を設定したいときは，個別に設定するようにする。Windows の場合は`terminal.integrated.env.windows`，Mac は`terminal.integrated.env.osx`，Linux は`terminal.integrated.env.linux`に設定する。

```json:settings.json
"terminal.integrated.env.linux": {
    "PATH": "<new path>;${env:PATH}"
}
```

# Git の場所を指定したいだけの場合

Linuxbrew で最新の Git をインストールして使っているのに，VSCode では Linux 標準の古い Git が読み込まれてしまっていて困っている，などという問題を解決したいだけ場合は WSL 側にある`settings.json`に以下を追記。

```json:.vscode_server/data/Machine/settings.json
 "git.path": "<path to git>"
```

# 全体に PATH の設定を反映したい場合

拡張機能によっては PATH の設定がうまくされていないと動かないものもあるだろう。
それぞれ個別に`settings.json`で指定できれば良いが，内部の依存ライブラリまで PATH の設定ができないかもしれない。

というか「そもそも VSCode を WSL で立ち上げる前に，PATH の設定くらい読み込んでおいてくれよ」と思うのは自然だろう。

これについて，[公式ドキュメント](https://code.visualstudio.com/docs/remote/wsl#_advanced-environment-setup-script)には以下のようにある。

> When VS Code Remote is started in WSL, no shell startup scripts are run. This was done to avoid issues with startup scripts that are tuned for shells. If you want to run additional commands or modify the environment this can be done in a setup script `~/.vscode-server/server-env-setup` (Insiders: `~/.vscode-server-insiders/server-env-setup`). If present, the script is processed before the server is started.

要するに，**VSCode Remote WSL を使うときは PATH の設定 (`.bash_rc`,`.bash_profile`など) は読み込まれないから，なんか設定したかったら WSL 上に`~/.vscode-server/server-env-setup`ファイルを作って書いてね**
ということである。

これでたとえば Linuxbrew に PATH を通しておけば，ちゃんとそちらのライブラリが読み込まれるようになる。

また，これを設定すれば，上2つの設定は不要である。
Dart とC言語の連携 : dart:js と dart:ffi の両立 (3) int doube 

[前回](https://qiita.com/kyorohiro/items/cffecf482ed784b6f1b0)の続きです。
int や double や pointer を使ってみましょう

# Int と Double を 使ってみる
### C言語の関数を作成する。 

```c:ky.c
#include <stdio.h>
#include <stdlib.h>
// [Linux]
// find . -name "*.o" | xargs rm
// gcc -Wall -Werror -fpic -I. -c ky.c -o ky.o 
// gcc -shared -o libky.so ky.o

// [Wasm]
// find . -name "*.o" | xargs rm
// find . -name "*.wasm" | xargs rm
// emcc ky.c -o ky.o 
// emcc ky.o -o libky.js -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' -s EXPORTED_FUNCTIONS="['_sum_int','_sum_double']"
// cp libky.js ../web/libky.js 
// cp libky.wasm ../web/libky.wasm

int sum_int(int a, int b){
    return a + b;
}

double sum_double(double a, double b) {
    return a + b;
}

```



### Dartから 関数を呼び出す:Linux Server

```dart:main.dart
import 'dart:ffi' as ffi;
import 'dart:typed_data' as typed;
// dart ./bin/main.dart

ffi.DynamicLibrary dylib = ffi.DynamicLibrary.open('/app/libc/libky.so');

// int sum_int(a,b)
typedef SumIntFunc = ffi.Int32 Function(ffi.Int32 a, ffi.Int32 b);
typedef SumInt = int Function(int a, int b);
SumInt _sum_int = dylib
      .lookup<ffi.NativeFunction<SumIntFunc>>('sum_int')
      .asFunction<SumInt>();
int sumInt(int a, int b) {
  return _sum_int(a, b);
}

// int sum_double(a,b)
typedef SumDoubleFunc = ffi.Double Function(ffi.Double a, ffi.Double b);
typedef SumDouble = double Function(double a, double b);
SumDouble _sum_double = dylib
      .lookup<ffi.NativeFunction<SumDoubleFunc>>('sum_double')
      .asFunction<SumDouble>();

double sumDouble(double a, double b) {
  return _sum_double(a, b);
}

void main(List<String> args) {
  // int
  print('${sumInt(10, 100)}'); // 110
  // double
  print('${sumDouble(10.1, 100.2)}'); // 110.3
  // pointer and buffer
}


```

### Dartから 関数を呼び出す:Webブラウザー

```dart:main.dart
import 'dart:js' as js;
import 'dart:typed_data' as typed;

// webdev serve --hostname=0.0.0.0
js.JsObject Module = js.context['Module'];

js.JsFunction _sum_int =  Module.callMethod('cwrap',['sum_int','number',['number', 'number']]);
int sumInt(int a, int b) {
  return _sum_int.apply([a, b]);
}

js.JsFunction _sum_double =  Module.callMethod('cwrap',['sum_double','number',['number', 'number']]);
double sumDouble(double a, double b) {
  return _sum_double.apply([a, b]);
}

js.JsFunction _to_uint8list= js.context['to_uint8list'];// from util.js
typed.Uint8List toUint8List(int buffer, int length) {
  return _to_uint8list.apply([buffer, length]);
}

void main() { 
  // int
  print('${sumInt(10, 100)}'); // 110
  // double
  print('${sumDouble(10.1, 100.2)}'); // 110.3

}

```

# 次回

Pointer と Buffer を扱ってみます。

# PS

今回のコードは以下です
https://github.com/kyorohiro/dart_clang_codeserver/tree/03_buffer_int_double

以下でも書いています
https://dev.to/kyorohiro/dart-and-c-how-to-ffi-and-wasm-3-int-doube-buffer-pointer-832
Web制作する人のための、見えにくい人が使っているスクリーンリーダーのことがわかる方法

# 前書き
ウェブアクセシビリティなんて言われてもどうすりゃいいんだよ、っていうことになるんじゃないだろうか。今は資料も増えてきたし、先人たちが頑張って活動してくれているので、ユーザーから見た状況もかなり良くなっていると思う。

一方、自分が実装したアクセシビリティ的な取り組みが、実際のユーザーにはどのように伝わっているのかがわかりにくい場合もあるのではと思う。実際に画面を見ないでコンピュータを使っている人に遭遇したことのあるエンジニアはそう多くはないだろうし、どのように画面が読み上げられるかを聞いたことのあるエンジニアも少ないのではないだろうか。

ということで、あなたのブラウザーに、音声読み上げ機能を更かしてみよう、というのがこの記事の内容である。

## NVDA

無料で使える画面読み上げ環境で、包括的に使えるのはNVDAというものだ。対応OSはWindows。

### 入手先など

[NVDA日本語サイト](http://www.nvda.jp)
からダウンロードしてインストールする。この環境でWindowsを使ってみると、いろいろと発見もあると思う。

### ウェブサイトを閲覧してみる

では、実際に使ってみよう。Chrome前提、Windows 10環境ということで話を進める。さあ、マウスを触らず、勇気があればアイマスクでもしてやってみよう。パソコンが起動して、NVDAがなにかしら喋ってることを確認しておこう。

1. Windowsキーを押しながらMを押す。これですべてのウィンドーが小さくなってデスクトップが表示されたはず
2. もう一度Windowsキーを押す。これで検索ボックスにフォーカスが行ったはず。
3. "chrome"と入力してみよう。１文字入力する毎に検索が行われて、数文字入力したところで"Google Chrome"という音声が聞こえるだろう。
4. "Google Chrome"が聞こえたらエンターキーを押す。これでChromeが起動できた。
5. Altキーを押しながらDを押す。これでアドレスバーにフォーカスが行った。
6. では、"qiita.com"とか入力してエンターキーを押す。


## ChromeVox

こちらはChromeBookに標準搭載されている画面読み上げ環境である。それをPC上のChromeの上で動くようにしたもの。Chromeが動けばこちらも動くのではないかと思うので、Windows以外の人も使える。

### 入手先など

[このページ](http://www.chromevox.com/installing.html)
を参考に、ChromeにChromeVoxを組み込む。

### ウェブサイトを閲覧してみる

1. Altキーを押しながらDを押す。これでアドレスバーにフォーカスが行った。
2. では、"qiita.com"とか入力してエンターキーを押す。

## どうやって操作すんの？

ページが開いたらなにやら喋りだしたんじゃないだろうか。なにを喋ってるか聞き取れるだろうか？ちゃんと日本語喋ってるだろうか？Windows 10ならばおそらく日本語を喋ってるのではないかと思う。もし日本語を喋っていないのならば、NVDA, ChromeVoxのオプションを調整して日本語がしゃべるようにする必要があるが、この方法については他に譲ろう。

では、読み上げ方法について少し書く。

### NVDA

原則的に、矢印キーを使ってページの中に書かれているテキストを読んでいく。上下の矢印キーを使えば1行ずつ、左右の矢印キーを使えば1文字ずつ確認ができる。

HTML要素名をキーにしたジャンプ機能が少しだけある。

* h : heading
* l : list

ちなみに、NVDAの終了は、Insertキーとqを押す。

### ChromeVox

NVDAと違い、上下矢印キーを押してもページの読み上げは行われない。これらのキーはそのままブラウザに送られる。

ChromeVoxの読み上げのためには、ChromeVoxキーという修飾キーと読み上げコマンドに対応するキーを押す。ページを読み上げたければ、デフォルト設定だとAlt+Shift+上下の矢印キーだ。文字の読み上げはデフォルトでは設定されていない。

Alt+Shift+.を押すとキーの一覧が表示されるだろう。これを参考にして操作してみてほしい。

## まとめ

どうだろう、こんな環境でウェブを閲覧している人が一定数存在するのだということが伝わればよいな。

音声というメディアには下記のような特徴がある。

* 順番に情報を聞くことになる
* すべての情報は同じ重みで伝わる
* 読み飛ばしが難しい
* その他にもあるよね、きっと

例えば、文字情報にしてしまうとほとんどが広告であるページなどは、本文を探し出すのにかなり苦労することになる。そこで適切なアクセシビリティ的な配慮がされているページというのが重要になる、というわけなのだ。

## おまけ

この記事、私がQiitaに登録した頃に書きかけて塩漬けになってたものを引っ張り出して書いている。この分野には多くの参考サイトがあり、優秀な記事がたくさんある。ということで、この記事を初めてのアクセシビリティの参考にしてしまったあなたは、ぜひ他の優秀な記事に目を通していただければと強く思う。
jsarticleにおける \@startsection のふしぎ

# 今回のテーマ

`\section` が内部で読み出している`\@startsection`という制御綴の定義がjsarticle.clsで上書きされていて，その変更理由が不思議に思えたので共有します。

## latex.ltxにおける仕様

```tex:
\def\@startsection#1#2#3#4#5#6{%
  \if@noskipsec \leavevmode \fi
  \par
  \@tempskipa #4\relax
  \@afterindenttrue
  \ifdim \@tempskipa <\z@
    \@tempskipa -\@tempskipa \@afterindentfalse
  \fi
  \if@nobreak
    \everypar{}%
  \else
    \addpenalty\@secpenalty\addvspace\@tempskipa
  \fi
  \@ifstar
    {\@ssect{#3}{#4}{#5}{#6}}%
    {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}}

```



## jsarticle.clsにおける仕様

```tex:
\def\@startsection#1#2#3#4#5#6{%
  \if@noskipsec \leavevmode \fi
  \par
  \@tempskipa #4\relax
  \if@english \@afterindentfalse \else \@afterindenttrue \fi
  \ifdim \@tempskipa <\z@
    \@tempskipa -\@tempskipa \@afterindentfalse
  \fi
  \if@nobreak
    \everypar{}%
  \else
    \addpenalty\@secpenalty
    \ifdim \@tempskipa >\z@
      \if@slide\else
        \null
        \vspace*{-\baselineskip}%
      \fi
      \vskip\@tempskipa
    \fi
  \fi
  \noindent
  \@ifstar
    {\@ssect{#3}{#4}{#5}{#6}}%
    {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}}
```

# 本題
今回話題に上げるのは，この部分です。
## latex.ltxにおける仕様（重要部分だけ抜き出し）

```tex:
  \if@nobreak
    \everypar{}%
  \else
    \addpenalty\@secpenalty\addvspace\@tempskipa
  \fi
```

## jsarticle.clsにおける仕様（重要部分だけ抜き出し）

```tex:
  \if@nobreak
    \everypar{}%
  \else
    \addpenalty\@secpenalty
    \ifdim \@tempskipa >\z@
      \if@slide\else
        \null
        \vspace*{-\baselineskip}%
      \fi
      \vskip\@tempskipa
    \fi
  \fi
  \noindent
```

`\@nobreak`がfalseであるときの挙動が変更されています。改ページ直後に`\section` が来たときに，jsarticle版だと，

```tex:
\null
\vspace*{-\baselineskip}%
```
というところで余分なスペースが出力されてしまいます。`\@srartsection`の引数の中で，必要な上下の空き幅については指定出来るはずですので，私が頭の中で思い浮かべる仕様と異なっている・・不思議です。
Javascriptでtweenerを自作する

##たまに作るような内容ですがコピペで使えるように、メモ的に書いています。

setIntervalで回数制限
https://ndruger.hatenadiary.org/entry/20100928/1285679176
イージングの使い方の確認
https://gist.github.com/gre/1650294
経過時間の参照
https://webbibouroku.com/Blog/Article/js-time

上記リンクを参考

EasingFunctionsはそのまま利用する（jsに直書きでもOK）

```js:qiita.js
function tweener(_time,_func,_ease){
   var start = new Date().getTime();
    var _si = setInterval(function(){
        var _progress = new Date().getTime() - start;
        if ( _progress > _time) {
          //1
          _func(1);
          clearInterval(_si);
        }else{
          //
          _func(_ease(_progress/_time));
        }
    }, 33);
}
```


これで使い方は

```js:qiita.js
tweener(3000,function(progress){
  console.log(progress)
},EasingFunctions.easeOutQuint);
```

こんな感じでprogressに0-1までの値で3秒間でeaseOutQuintで値が出てくるので変数に当てはめればいい。

でこれで終わりでもいいのですが、途中で止めるっていうのも欲しい。やめ方も
skipで終了値にする、cancelで初期値にする、killで止めるっていうのができたらいいので追加すると


```js:qiita.js
var TWEENER = {
  tween:function(_time,_func,_ease){
    var start = new Date().getTime();
    var _this = this;
    _this.functionHolder = _func;
    _this.setIntervalObj = setInterval(function(){
        var _progress = new Date().getTime() - start;
        if ( _progress > _time) {
          //1
          _func(1);
          _this.functionHolder = null;
          clearInterval(_this.setIntervalObj);
        }else{
          //
          _func(_ease(_progress/_time));
        }
    }, 33);
  },
  cancel:function(){
    if(this.functionHolder != null){
      this.functionHolder(1)
      clearInterval(this.setIntervalObj);
    }
  },
  skip:function(){
    if(this.functionHolder != null){
      this.functionHolder(1)
      clearInterval(this.setIntervalObj);
    }
  },
  kill:function(){
    clearInterval(this.setIntervalObj);
  },
  functionHolder:null,
  setIntervalObj:null
}
```

で使い方は

```js:qiita.js
TWEENER.tween(3000,function(progress){
  console.log(progress)
},EasingFunctions.easeOutQuint);

setTimeout(function(){
  TWEENER.cancel();
},1000);
```
※無理やり１秒後にcancelをしています
な感じで自前でtweenerが完成。
Unreal Engine 4 の Third Person Example のキャラを Infinity Blade のキャラに交換する

簡単にできそうなのに、やり方がどこにも書いてない気がしたので、忘れないように書いておきます。

ちなみに、2020/5/18 時点では Infinity Blade のキャラクタのアセットは 4.25 には対応してないと言われて、プロジェクトに追加できません。4.24.3 ならいけます。

# 準備

- Windows 10 Home
- Unreal Engine 4.24.3
- Infinity Blade の無料のキャラをダウンロードしておく

ここでは、下記のキャラを使っていますが、他のキャラでも同様にできる（はず）。

- [Paragon: Phase：Epic Games：Epic Content](https://www.unrealengine.com/marketplace/ja/product/paragon-phase/reviews?sessionInvalidated=true)

# 手順１

Unreal Engine を起動する。「ゲーム」のテンプレートの中から「サードパーソン」のテンプレートを選ぶ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/e7c37638-1be4-7898-11a3-64667990e938.png)

プロジェクトの設定はデフォルトでOK。プロジェクトの名前は適当に入れる。ここでは InfinityTest としている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/2c73c102-4b49-6b71-80a2-68eef0f6ae1a.png)

「次へ」を押すとプロジェクトが作成されて、アプリを実行できる状態になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/9f3f330c-496e-bdf2-82c8-37e08e9c7f9e.png)

マーケットプレイスの「無料」「Epic Games コンテンツ」で Infinity Blades のキャラのいずれかを購入（無料）して、作成したプロジェクトに追加する。キャラクタのデータは1GB程度はあるので、初回だけダウンロードに時間がかかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/0a0b8035-3aaa-1554-cf5e-419940bf6f89.png)

インポートされたら、画面右側のアウトライナから ThirdPersonCharacter を探してクリックする。

Anim Class をキャラクタ名 + AnimBlueprint にして、Skeltal Mesh をキャラクタ名のものに変更する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/4d44f755-30ad-240b-7755-dbbc28dcecff.png)

これで動くはず。

## まとめ

簡単にできすぎるからかもしれないけど、やり方の書かれたページを見つけられなくて、無駄に苦労してしまった。
備忘録　Ruby 『p』と『puts』の違い

2020/05/17

Atcoderで競技プログラミングをしていたときに、
やらかしてしまったミスを備忘録として残しておく。


##Atcoder168_B

出力に以下が表示されればOK

```
$ ruby Bmain.rb 
4　#入力
aaaaa　#入力
aaaa... #出力
```

以下のようなコードを書いた。

```

K = gets.to_i
S = gets.chomp

if S.length <= K then
  p S
elsif S.length > K then
  p S[0..(K-1)]+"..."
end
```

出力
出力に""が表示されてしまっているためエラーとなる。

```
$ ruby Bmain.rb 
4 #入力
aaaaa　#入力
"aaaa..."　#出力
```


pをputsに変更

```
K = gets.to_i
S = gets.chomp


if S.length <= K then
  puts S
elsif S.length > K then
  puts S[0..(K-1)]+"..."
end
```

次は、""なしで表示された。

```
$ ruby Bmain.rb 
4　#入力
aaaaa　#入力
aaaa... #出力
```

pはデバッグ用途で使用するためのものなのでわかりやすいように""をつけるとのこと。
【Python】隣接行列・隣接リストの作り方と相互変換【グラフ理論】

# はじめに
競技プログラミングを行っていると、遅かれ早かれぶつかる壁が「グラフ理論」です。今回はPythonでの「隣接行列 (Adjacency matrix) 」と「隣接リスト (Adjacency list) 」の基本の作成方法をコード付きでまとめました。問題によっては自身の手で変形してください。

# 隣接行列と隣接リスト
例えば、以下のようなグラフを考えます。
<img width="300" alt="g.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363619/4a116f57-5a60-355c-b732-65ea19cafa06.png">

コンピュータ上でのグラフのデータ構造は大きく2種類あります。状況に応じて使い分けましょう。
一つは`隣接行列`で、$n\times n$ の行列形式になります。メモリの使用量が多いですが、定数時間で特定の辺があるかどうかを判別できるというメリットがあります。

```text:adj_m.txt
[[0, 1, 1, 0, 1],
 [1, 0, 1, 1, 0],
 [1, 1, 0, 1, 1],
 [0, 0, 1, 1, 1],
 [1, 0, 1, 1, 0]]
```

もう一つは`隣接リスト`です。メモリの使用量が少ない反面、特定の辺があるかどうかの判定に、最悪 $O(V)$ の時間がかかるというデメリットがあります。

```text:adj_l.txt
[[2, 3, 5], [1, 3, 4], [1, 2, 4, 5], [2, 3, 5], [1, 3, 4]]
```

実際の問題では、[AtCoder Beginners Contest 168 D .. (Double Dots)](https://atcoder.jp/contests/abc168/tasks/abc168_d)のような、`辺の2つの端点`が与えられることが多いです。

今回のグラフに対する入力を表現しようとすると以下のようになります。(1行目に頂点の数`n`と辺の数`m`が入力されています)

```text:input.txt
5 8
1 2
1 3
1 5
2 3
2 4
3 4
3 5
4 5
```

# Pythonコード
入力の隣接行列と隣接リストへの変換とそれらの相互変換のチートシートを書いていきます。

## 入力 to 隣接リスト
辺の重みがない場合。

```python
n, m = map(int, input().split())
graph = [[] for _ in range(n)]
for _ in range(m):
    a, b = map(int, input().split())
    graph[a-1].append(b-1)
    graph[b-1].append(a-1)  # 有向グラフなら消す
print(graph)  # [[2, 3, 5], ..., [1, 3, 4]]
```

辺の重みがある場合。

```python
n, m = map(int, input().split())
graph = [[] for _ in range(n)]
for _ in range(n):
    u, v, w = map(int, input().split())
    graph[u-1].append([v-1, w])
    graph[v-1].append([u-1, w])  # 有向グラフなら消す
print(graph)  # [[2, 3], [3, 1], [5, 9]], ..., [...]]
```

## 入力 to 隣接行列
辺の重みがない場合。

```python
n, m = map(int, input().split())
graph = [[0]*n for _ in range(n)]
for _ in range(m):
    a, b = map(int, input().split())
    graph[a-1][b-1] = 1
    graph[b-1][a-1] = 1  # 有向グラフなら消す
print(graph)  # [[0, 1, 1, 0, 1], ..., [1, 0, 1, 1, 0]]
```

重み有りの場合。

```python
n, m = map(int, input().split())
graph = [[0]*n for _ in range(n)]
for _ in range(m):
    u, v, w = map(int, input().split())
    graph[u-1][v-1] = w
    graph[v-1][u-1] = w  # 有向グラフなら消す
print(graph)  # [[0, 2, 3, 0, 1], ..., [2, 0, 3, 0, 0]
```

## 隣接リスト to 隣接行列
辺の重みがない無向グラフを対象としています。
隣接リストが`graph`、隣接行列が`graph_new`です。

```python
graph_new = [[0]*n for _ in range(n)]  # 隣接行列
for i, g_i in enumerate(graph):
    for j in g_i:
        graph_new[i][j] = 1
print(graph_new)
```

## 隣接行列 to 隣接リスト
辺の重みがない無向グラフを対象としています。
隣接行列が`graph`、隣接リストが`graph_new`です。

```python
graph_new = []
for i in range(n):
    tmp_l = []
    for j in range(n):
        if graph[i][j] > 0:
            tmp_l.append(j)
    graph_new.append(tmp_l)
print(graph_new)
```

# おわりに
お読み頂きありがとうございました。間違いや誤字等があれば教えて頂けると嬉しいです。
[Flutter]画像をドラッグすることでカウンターを動かす

# はじめに
Draggable widgetを使って画像をドラッグできるようにし、さらに指定の領域と重なったときに関数を実行する方法を示します。

今回は初期で作られるカウンターアプリを改変して、ピーターパン症候群のおじさんがリュウグウノツカイと重なるとカウンターが１増えるアプリを作りました。
![画面収録 2020-05-18 2.06.46.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/32526f98-d7c9-364b-f76a-e1b8450f2cbd.gif)

# 実装
①ピーターパン症候群のおじさんの画像をDraggableで囲む
②リュウグウノツカイの画像をDraggableTargetで囲む
③重なったときにカウンターを動かす関数をonWillAccept内に記載する

```dart
// ①
Draggable(
  child: Image.network(
    // 移動させる画像
    'https://3.bp.blogspot.com/-QxAapI2H1Pk/VhSAsJpLPhI/AAAAAAAAzG0/80qjXfZlomk/s800/peterpan_syndrome.png',
    width: 200,
    height: 200,
  ),
  feedback: Image.network(
    // ドラッグ中の画像
    'https://3.bp.blogspot.com/-QxAapI2H1Pk/VhSAsJpLPhI/AAAAAAAAzG0/80qjXfZlomk/s800/peterpan_syndrome.png',
    width: 220,
    height: 220,
  ),
  childWhenDragging: Opacity(
    // 移動させた元の場所に表示する画像
    opacity: 0.0, // 完全に透明にする
    child: Image.network(
      'https://3.bp.blogspot.com/-QxAapI2H1Pk/VhSAsJpLPhI/AAAAAAAAzG0/80qjXfZlomk/s800/peterpan_syndrome.png',
      width: 200,
      height: 200,
    ),
  ),
  data: 'data',
),
// ②
DragTarget(
  // ドラッグ先の領域
  builder: (context, accepted, rejected) {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(
          color: _willAccepted ? Colors.orange : Colors.transparent,
          width: _willAccepted ? 1 : 1,
        ),
      ),
      width: 600,
      height: 300,
      child: Center(
        child: Image.network(
'https://4.bp.blogspot.com/-6Sr0RZ5rlAQ/UYh8w3M6Z_I/AAAAAAAARRY/_c7ewyEIZYY/s400/shinkai_ryugunotsukai.png'),
      ),
    );
  },
  // ③
  onWillAccept: (data) {
    // 領域と重複したときの処理
    _incrementCounter();
    _willAccepted = true;
    return true;
  },
  onLeave: (data) {
    // 領域から離れたときの処理
    _willAccepted = false;
  },
),

```
ドロップしたときの処理など、まだまだ他にもできることはあります。ぜひ下記を参考にしてみてください。
[公式ドキュメント](https://api.flutter.dev/flutter/widgets/Draggable-class.html)
[【Flutter】ドラッグ&ドロップの実装](https://qiita.com/umechanhika/items/2f572f7b58f0316b4faf)



# 参考
https://api.flutter.dev/flutter/widgets/Draggable-class.html
https://qiita.com/umechanhika/items/2f572f7b58f0316b4faf
Rubyの基礎2~わかりにくいところ復習~

####メソッド
メソッドは使えるオブジェクトが決まっている。
eachメソッドの場合は配列オブジェクトや範囲オブジェクトにしか使えません。
また、eachメソッドを配列オブジェクトに使った場合の返り値は配列オブジェクトそのものです。

####クラス
クラスとは、とあるオブジェクトの共通の属性とメソッドをまとめておく型のようなもの。
"Hello"と"こんにちは"はそれぞれ別のオブジェクトですが、文字を持つと言う点においては共通です。
この性質は予めクラスの性質として定義されているものなのです。
この型を予め用意しておけば、その肩に沿って効率的にオブジェクトを生成できます。

####インスタンス
クラスから生まれたオブジェクトのことをインスタンスと言います。
オブジェクトから先に生まれることはなく、クラスからインスタンスというオブジェクトが生まれます。
属性と属性値とメソッドが入った状態でインスタンスが生成されます。
つまり、クラスで属性が定義されていて、具体的な属性値を持った状態でインスタンスが生成されます。

例えば文字列オブジェクトの "Hello" は Stringクラスで定義された属性=文字に、属性値="Hello"が入った状態、かつlengthメソッドやto_iメソッドなどのメソッドを持った状態でインスタンスが生成されます。

#####Rubyに予め定義されているクラス
Rubyには予め定義されたクラスがある。
文字列オブジェクトのStringクラス
配列オブジェクトのArrayクラス
数値オブジェクトのIntegerクラス
ハッシュオブジェクトのHashクラス

#####newメソッド
newメソッドは全てのクラスで定義しなくても使うことができます。
newメソッドを使うことによってインスタンスを生成できます。
返り値として利用したクラスのインスタンスを返します。
クラスメソッドである。なぜならインスタンスを生成するのはクラスが行うべきだから。

#####クラスメソッド
クラスメソッドはクラスメソッドを定義したクラス自身が利用できるものでクラスで共通の情報を使った処理に使います。
メソッド名の前に`self`をつけます。

#####インスタンスメソッド
インスタンスメソッドは、インスタンスが利用できるメソッドです。インスタンスメソッドを定義したクラスのインスタンスに使用できる。インスタンスごとの個別の情報を使った処理に使えます。


#####クラスメソッドとインスタンスメソッドの違い

|   特徴            　| インスタンスメソッド        |  クラスメソッド           |
|:-------------------|:---------------------|:--------------------|
| 定義方法           |メソッド名の前に selfを付けない|メソッド名の前にselfを付ける |
| 用途     　　　　   |インスタンスごとの属性を用いるとき|属性が関係のない共通の処理をするとき|
| 呼び出せるオブジェクト  |クラスのインスタンス|クラス自身|
| 呼び出し方 　　　　 | インスタンス名.メソッド名（引数）|クラス名.メソッド名（引数）|

####クラスの変数
クラスでは共通の属性は変数を使って定義します。
その変数に代入した値が属性値です。
クラスに定義できる変数は、クラス変数とインスタンス変数があります。

#####クラス変数
クラス変数はクラス全体で使用できる変数です。つまり、クラスメソッド内でもインスタンスメソッド内でも使用することができます。クラスを通して値が共通の情報に使用する変数。

#####インスタンス変数
インスタンス変数は、共通の属性としてインスタンスに定義できる変数です。
値はそれぞれのインスタンスごとに設定できます。
各インスタンスでのみ使用ができます。
定義場所はインスタンスメソッド内で行います。
インスタンスメソッド内で定義されたインスタンス変数の値は、そのインスタンスメソッドを利用したインスタンスが持つインスタンス変数の値になる。

#####initializeメソッド
initializeメソッドはインスタンスを生成したと同時に実行したい処理を自動で実行できます。


#####クラスの継承
あるクラスに定義されたメソッドを別のクラスで利用できるようにすることを継承と言います。
継承したいクラスのことを親クラスといい継承する側のクラスのことを子クラスと言います
class 子クラス名 < 親クラス名　で親クラスを継承できます。


#####pメソッド
pメソッドはpの右側に書かれたオブジェクトやインスタンスを出力するものです。putsメソッドと似ていますがputsメソッドが返り値nilを返すのに対しpメソッドはそのオブジェクトやインスタンス自体を返り値として返します。

####for文
while文と同じ繰り返しを行う文法です。

```
for num in 1..10 do
  puts num
end

変数numに１〜１０を代入して出力しています。
inの後ろにあるオブジェクト順番に変数numに代入しています。
1..10は１~10という意味です。
【Swift】RxSwiftでボタンのタップイベントを拾う

`RxSwift`はボタンのタップイベントと`TableView` `CollecrionView`の実装が格段に楽になるので大好きです。
今回はボタンのタップイベントの実装をいくつかご紹介します。

## subscribe(_ on:)を使う
##### subscribe(_ on:)の説明
`Subscribes an event handler to an observable sequence.
- parameter on: Action to invoke for each event in the observable sequence.
- returns: Subscription object used to unsubscribe from the observable sequence.
`
つまり監視できるもののイベントを拾えるのです。
これを使って`Button`のタップイベントを拾うとこんな感じになります。

```swift
button.rx.tap.subscribe({ [weak self] _ in
    // ボタンタップでキックしたいアクションを記述
    }).disposed(by: disposeBag)
```
`[weak self]`は`[unowned self]`でももちろんOKですが、私は管理が面倒なので`[weak self]`を使うことが多いです。
循環参照一度起こすと結構調査が面倒だし、平気でクラッシュするから脳筋`weak`しちゃうんですよね。。

[[weak self]と[unowned self]についてはこちらの記事が面白かったです](https://medium.com/eureka-engineering/rxswift%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%9E%E3%83%AB%E3%83%81%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E3%81%AE%E7%90%86%E8%A7%A3%E3%82%92%E6%B7%B1%E3%82%81%E3%82%8B-scheduler%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-2471ec76e518)

## bind<Observer>(to observers:)を使う
私は普段この実装方法を取り入れていることが多いです。

```swift
private func setButton() {
    button.rx.tap.bind(to: buttonTapBinder).disposed(by: disposeBag)
}

private var buttonTapBinder: Binder<()> {
    return Binder(self) { base, _  in
        base.button.isSelected = !base.button.isSelected
    }
}
```
`Binder`を使用しているので、循環参照は自ずと防がれるので結構使ってます。
`subscribe`の実装もそうですが、どちらもボタンのタップだけではなく、他のイベントの監視もできるのでぜひ応用してみてください！

##### RxSwiftに関する記事
[【Swift】RxSwiftを使ったTableViewの実装（Delegate/reloadDataは使わない！）](https://qiita.com/_asa08_/items/f12e5a03ea5433b89e8b)
Visual Studio2019でtalibをダウンロードが上手くいったのでまとめてみた

windows10 64bit, python3.7, VisualStudio Community 2019の環境でTA-Libをインストールしようとしたらやっぱり躓いたので、同じく躓いた人が参考になるように解決方法をここに記します。

------------------------------------------------
**結論**

下記でも述べますが，pythonのパッケージをインストールするときはVisualStudioのインストーラを使ってました。
↓このようなもの
![visualstudio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609281/d63da4af-750b-6df8-35af-32c9fc1ed23f.png)

ですが，VisualStudioに付属されているコマンドプロンプト「[developer command prompt](https://docs.microsoft.com/ja-jp/dotnet/framework/tools/developer-command-prompt-for-vs)」を使って，元々コンパイルされている.whlファイル「TA_Lib-0.4.18-cp37-cp37m-win_amd64.whl」をインストールすれば大丈夫です。
※[.whlファイル](https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib)はリンク先からダウンロード可能

その手順を書きます。

**①コンソールでpipコマンドを使えるようにする**
[developer command prompt](https://docs.microsoft.com/ja-jp/dotnet/framework/tools/developer-command-prompt-for-vs)を起動して，下記のコマンドを入力することで，pipコマンドを使えるようにする。

```ここに言語を入力
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community>py -m pip install pypdf2
```

**②C:\Program Files (x86)\Microsoft Visual Studio\2019\Community>配下に対象の.whlファイルを置く**
↓こんな感じ
<img width="528" alt="explore.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609281/97f3c1c4-af44-653e-fb41-f3df4d73f5f5.png">

**③.whlファイルをインストール**

```ここに言語を入力
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community>py -m pip install TA_Lib-0.4.18-cp37-cp37m-win_amd64.whl
```

**④VisualStudioでTA-Libをインストール**
![visualstudio2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609281/028a41e5-ad97-95ca-e5eb-284b8c85e950.png)

以上が手順になります。
半日以上かかったのに記事にするとあっけなかったです…
VSCode でドローイング / drawio を使う

# VSCode で drawio を使う

VSCode にドローイングツール drawio のプラグインが提供されるようになった、ということでインストールしてみた。

[Draw\.io Integration \- Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio)

drawio については詳しくは述べないが、Apache 2.0でライセンスされているオープンソフトウェアで、以前はWEBサービスとして動かすものだったと記憶しているが、いつの間にかオフライン版が提供されるようになっていたらしい。

ソフトウェアの仕事をしているとチャートやブロック図、UMLなど図を描きたいと思うシーンがそれなりの頻度で出るにも関わらず気軽に使える適切なツールがなく、ついつい Excel を使用、そして履歴管理や構造を取り出すといったことを使用として途方に暮れるも過去の資産や手軽さでそれを超えるものがなく、ついつい使い続けてしまう…という経験をしている人も少なくないのでは、と思う。

客先に提出したり、図表が成果物として定義されていれば Visio を導入したりと言ったこともあるのだろうが…残念ながらこの20年以上、図表を描く必要性が低すぎて、導入する→便利で使い倒す→効率が上がる→広く導入する→…、というスパイラルを組み立てることができなかった。


## 導入

拡張機能の管理(MarketPlace)から ```drawio``` で検索、インストール。 これだけ。
同様な拡張機能に、```vscode-drawio``` というのもあるが、```Draw.io Integration```のほうが 2020-05-17 記事投稿時点で既にメニューが日本語化されており、カスタマイズも多いようだ。

インストール後、拡張子```.drawio``` ```.dio``` ```.drawio.svg``` でファイルを作成するとVSCode内でdrawioエディタが起動する。デフォルトではオフライン版の drawio が動作するが、外部のdraw.ioサービスも利用できる。

あまりの導入の容易さに拍子抜け。

## 設定

[Draw\.io Integration \- Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio)
に詳しいが、オンライン/オフラインの切り替え、テーマの切り替えの他、

* 拡張子```.svg```の関連付け
* XMLファイルを直接編集しながら図の確認ができる

などなど