OmniAICreator/Qiita-1.07M huggingface dataset:
Kotlinでデザインパターン Adapter編

# はじめに

本記事は[Java言語で学ぶデザインパターン入門](http://www.hyuki.com/dp/)を参考にしながら
JavaではなくKotlinで実装してみようというものです。

![Java言語で学ぶデザインパターン入門](http://www.hyuki.com/images/dp1.png)

# 調べてみる

Adapterについて調べてみます。
[Wikipedia](https://ja.wikipedia.org/wiki/Adapter_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)ではAdapterについて次のように解説されています。

```
Adapter パターン（アダプター・パターン）とは、GoF (Gang of Four; 4人のギャングたち) によって定義されたデザインパターンの1つである。
Adapter パターンを用いると、既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。
Adapter パターンを実現するための手法として継承を利用した手法と委譲を利用した手法が存在する。
```

またAdapterはWrapperとも呼ばれるみたいです。
私の周りではWrapperと呼ぶ方が多いですね、
恐らくAdapterよりWrapperのほうがイメージしやすいからだと思います。

```
AdapterパターンはWrapperパターンと呼ばれることもあります。
引用:Java言語で学ぶデザインパターン入門 Adapterパターン P16
```

だらだらと調べたことをまとめると
- Adapterは既存のクラスを修正せずにインタフェースを変更する
- Adapterは継承または移譲を利用して実装できる
- AdapterはWrapperとも呼ばれる

# 実装してみる

今回はそのまま実装しても面白くないので例を変えたいと思います。

# Counter

既存のクラスとしてCounterを用意しました。
Counterは単純に数をインクリメント・デクリメント・リセットします。

```kotlin
open class Counter {

    var count : Int = 0
    fun increment() { count++ }
    fun decrement() { count-- }
    fun reset() { count = 0}
}
```

# Entrance

Entranceは入退室を管理し入室人数を数えるためのインタフェースです。
今回はCounterにAdapterパターンを適応して、このインタフェースを実現します。

```kotlin
interface Entrance {
    val headcount : Int
    fun enter()
    fun exit()
    fun exitAll()
}
```

# EntranceCounter

EntranceCounterがAdapterの役目を果たしEntranceのインタフェースを実現します。
はじめに述べたようにAdapterでは継承か移譲で実現するパターンがあります。
なので継承と移譲の2つのパターンを次のように実装します。

## 継承

```kotlin
class EntranceCounterInheritance : Counter() {
    val headcount : Int  get () = super.count
    fun enter() { super.increment() }
    fun exit() { super.decrement() }
    fun exitAll() { super.reset()}
}
```

## 移譲

```kotlin
class EntranceCounterDevolution : Entrance {
    private val counter : Counter = Counter()
    override val headcount : Int  get () = counter.count
    override fun enter() { counter.increment() }
    override fun exit() { counter.decrement() }
    override fun exitAll() { counter.reset()}
}
```

EntraceとCounterの「is-a」関係にはなっていないので、
今回は継承よりも移譲で実装するのが相応しそうです。
（このパターンの継承はただコードを共通に使えるからしちゃったってやつですね…）

# Main

作成したEntranceの動作確認をします。
出力結果からわかるようにCounterのインタフェースを変更でき上手く動作しています。

```kotlin
fun main(args : Array<String>) {

    val east : Entrance = EntranceCounterInheritance()
    val west : Entrance = EntranceCounterDevolution()

    east.enter()
    println("東 ${west.headcount}人 入室中")
    east.exit()
    println("東 ${west.headcount}人 入室中")
    east.enter()
    println("東 ${west.headcount}人 入室中")
    east.enter()
    println("東 ${west.headcount}人 入室中")
    east.exitAll()
    println("東 ${west.headcount}人 入室中")

    west.enter()
    println("西 ${west.headcount}人 入室中")
    west.exit()
    println("西 ${west.headcount}人 入室中")
    west.enter()
    println("西 ${west.headcount}人 入室中")
    west.enter()
    println("西 ${west.headcount}人 入室中")
    west.exitAll()
    println("西 ${west.headcount}人 入室中")
}

Output
--------
東 1人 入室中
東 0人 入室中
東 1人 入室中
東 2人 入室中
東 0人 入室中
西 1人 入室中
西 0人 入室中
西 1人 入室中
西 2人 入室中
西 0人 入室中
```
Swift：押した時に画像が変わるNSButton

```swift:
let btn = NSButton(frame: NSRect(x: 5, y: 5, width: 60, height: 40))
        
override func awakeFromNib() {
    super.awakeFromNib()
    btn.title = ""
    btn.image = NSImage(named: "image.png")
    btn.alternateImage = NSImage(named: "highlighted_image.png")
    btn.imageScaling = NSImageScaling.scaleProportionallyDown
    //重要なのはこれ↓
    btn.setButtonType(NSButton.ButtonType.momentaryChange)
            
    // btn.wantsLayer = true
    // btn.layer?.cornerRadius = 12
    // btn.isBordered = false
            
    btn.target = self
    btn.action = #selector(push)
    addSubview(btn)
}                

@objc func push() {
    print("hey")
}
```
[ほぼ自分用メモ] pythonでメールを送る [簡単]

#pythonでyahoo.co.jp からメールを送信

```python:send_email.py
#!/usr/bin/env python

import smtplib
smtp_obj=smtplib.SMTP_SSL('smtp.mail.yahoo.co.jp', 465)
smtp_obj.ehlo()
smtp_obj.login('your_address@yahoo.co.jp', 'secret_passwd')
smtp_obj.sendmail('your_address@yahoo.co.jp', 'someone_email_address', 'Subject: Good news!\n\nPython job has finished!')
smtp_obj.quit()
```

##メモ
- python2.7と3.6の両方で実行可能。
- メールの件名と本文の間に改行コードが2個必要だった。なぜかは解らない。。。
- 時間のかかるスクリプトの最後にこれを書いて、自分の別のメールアドレス宛にメールを送ると、ジョブが終わったことがわかるので便利だと思う。
Cytoscapeの場所を指定した描画方法


Cytoscapeでネットワーク図を描こうと思った時に少しはまった個所をメモ
Cytoscapeの基本的な部分は後日まとめる予定ですが気になる方は下記のドキュメント参照してください

http://js.cytoscape.org/


ポイント

```
  layout: {
    name: 'preset'
  },
```

## コード

### html

```
<!doctype html>
<html>
<head>
    <title>Tutorial</title>
    <meta charset="UTF-8">
    <script src="lib/cytoscape.min.js"></script>
    <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="js/jquery-ui.min.js"></script>
    <link rel="stylesheet" href="css/cytoscape.css">
</head>

<body>
    <div id="cy"></div>
    <script src="js/glaph.js"></script>
</body>
</html>
```

### glaph.js

描画設定を行っているjavascript
elements属性の定義で各nodeでpositionを設定する
左上がx:0,y:0地点

```
var sample_data = [
    { data: { id: 'A' }, position: { x: 100, y: 100 } },
    { data: { id: 'B' }, position: { x: 300, y: 100 } },
    { data: { id: 'C' }, position: { x: 100, y: 300 } },
    { data: { id: 'D' }, position: { x: 300, y: 300 } }
]

var style = [
    {
        selector: 'node',
        style: {
            shape: 'square',
            'background-fit': 'cover cover',
            'background-image-opacity': 0.5,
            'background-color': '#bbb',
            label: 'data(id)'
        }
    }
]

window.onload = function () {
    var cy = cytoscape({
        container: document.getElementById('cy'),
        elements: sample_data,
        style: style,
        layout: {
            name: 'preset'
        }
    })
}
```

cytoscape.css

```
#cy {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0px;
    left: 0px;
}
```

## まとめ
layoutで'preset'を指定しないと自動で位置を決定されてしまうので設定すること
Amazon API GatewayのWebsocketを試す

##はじめに

2018/12/19にAPI gatewayがwebsocketに対応したのでためしみてみます。

https://aws.amazon.com/jp/blogs/news/announcing-websocket-apis-in-amazon-api-gateway/

以下のサンプルになります。
https://github.com/aws-samples/simple-websockets-chat-app

###作成する構成

![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/7fd9033c-cafd-2d91-e206-8f62d3b144f4.png)

クライアントからWebsocketで接続に行くと、onConnect関数が実行され、コネクションIDがDynamoDBに登録されます。
メッセージを添えてsendMessageアクションを実行すると、sendMessage関数がDynamoDBに保存されたコネクションIDに対して、メッセージを送信する。

##手順

###赤枠の構成をCloudFormationで作成
SAMで作成したcFnテンプレートがS3のバケットを準備しておきます。
git cloneしてSAM/cFn実行します。

```
git clone https://github.com/aws-samples/simple-websockets-chat-app.git
cd simple-websockets-chat-app
sam package --template-file template.yaml --output-template-file output.yaml --s3-bucket <S3バケット>
aws cloudformation deploy --template-file output.yaml --capabilities CAPABILITY_IAM --stack-name websocket-test
```
###青枠のAPI Gatewayの構築

Create APIをクリックする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/37c180a7-7b5d-c414-8aaa-b4776ac69dcd.png)

WebSocketを選択する。
API Name: WebSocketと入力する。
Route Selection Expression：$request.body.action
Create APIをクリックする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/a785aa1d-90e5-fdc8-0842-f5ca6871ca1b.png)

sendmessageルートを作成する。sendmessageと入力に右横のチェックマークをクリックする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/10c01ec6-fa8a-542a-02b4-e0f59e804c00.png)

connectルートにonConnect関数を登録する。
Integration Requestをクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/5868976d-ddf1-f808-525e-97152b2848df.png)

Lambda FunctionにStack名-OnConnect-Functionxxxxを指定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/4eb92387-6ec1-9c8c-8047-d7ea892b475a.png)

上記を、disconnect/sendmessage/default分繰り返します。
defaultは、選択式がAPIルート内の他のrouteKeyに一致しない値を生成する場合に使用されます。今回は特にエラーハンドリング用の関数がないので、仮にonConnectを指定します。
何かしら紐づけておかないとAPIをデプロイするときにエラーになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/a585fbf4-10d2-db01-d089-9f6e94648aa0.png)

APIをデプロイする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/42f84de5-101c-105f-5aff-bcada189aa43.png)

APIデプロイ完了。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/78184/28c82db7-d845-8cc7-fb19-e10a76abb2b4.png)

###確認
NPMをインストールしてwscatをインストールする。

```
npm install -g wscat
```

メッセージ送信用と受信用のターミナルを開いてWebsocketで接続する

```
wscat -c wss://<API ID>.execute-api.<Region>.amazonaws.com/dev
connected (press CTRL+C to quit)
> 
> 
```

以下のJSONを入力する

```json
{"action":"sendmessage", "data":"hello world"}
```

受信用のターミナルでメッセージが表示されることを確認する。

```
connected (press CTRL+C to quit)
< hello world
> 
```

##お約束
投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。
Bash 5.0の新機能：localvar_inherit

Bash 5.0のNEWSファイルをさくっと翻訳したエントリー[「bash 5.0のNEWSファイル私訳」](https://qiita.com/emasaka/items/47eaa5fb5a01572fcc17)を先日書きました。

この中に、localvar_inheritという新しいshoptオプションが追加されたことが書かれています。

```
o. 新しいshoptオプション：localvar_inherit。設定すると、ローカル変数
   は、直前のスコープにある同じ名前の変数の値を継承します。
```

自分で訳しておいてなんですが、わかりにくいですね。

Bash 5.0のmanpageでは、こう説明されています。

```
localvar_inherit
        If set, local variables inherit the value and attributes
        of a variable of the same name that exists at a previous
        scope before any new value  is  assigned.   The  nameref
        attribute is not inherited.
```

やはりわかりにくいですね。

そこで、ちょこっと調べて試してみた結果を、順を追って説明します。

## おさらい①：関数

多くのプログラミング言語と同じく、Bashでも関数を定義できます。定義した関数はコマンドとして実行できます。

```bash
$ cat hello.sh
hello() {               # helloという関数を定義
    echo hello
}

hello                   # helloを実行
$ bash ./hello.sh
hello
```

## おさらい②：ローカル変数

単純なシェルでは変数はグローバル変数しかありません。しかしBashでは、`local`コマンドによって関数内のローカル変数を定義できます。

```bash
$ cat localvar.sh
foo() {
  local aaa     # aaaというローカル変数を定義
  aaa=5         # aaaに5を代入
}

aaa=3           # aaaに3を代入
foo             # fooを実行
echo $aaa       # その後でaaaの値は？
$ bash ./localvar.sh
3
```

## おさらい③：ローカル変数はダイナミックスコープ

Bashのローカル変数のスコープは、呼び出し先の関数でも有効です。Common Lispのスペシャル変数や、Emacs Lispのデフォルトのダイナミックスコープ変数、Perlのlocalなどに似ています。

次のように、関数fooと、fooから呼び出す関数barを定義します。すると、fooで定義したローカル変数aaaがbarからも参照できます。

```bash
$ cat scope.sh
foo() {
  local aaa=3   # aaaというローカル変数を定義して値を3に
  bar
}

bar() {
  echo $aaa     # barでのaaaの値は？
}

foo
$ bash ./scope.sh
3
```

同じ変数aaaを参照しているので、barで値を変更すると、fooでも変更されています。

```bash
$ cat scope2.sh
foo() {
  local aaa=3   # aaaというローカル変数を定義して値を3に
  bar
  echo $aaa     # barを呼び出した後でaaaの値は？
}

bar() {
  aaa=5         # barでaaaに5を代入
}

foo
$ bash ./scope2.sh
5
```

## ようやく本題：localvar_inherit

では、Bash 5.0の新機能であるlocalvar_inheritを見てみましょう。

localvar_inheritをオンにすると、呼び出し元の変数と同じ名前の変数を`local`で定義したときに、呼び出し元の変数の値と属性が **コピー** されます。

次の例では、fooとbarで同じ名前の変数aaaを定義しています。barではaaaの値を代入していないのに、fooでaaaに設定した値が参照されます。

```bash
$ cat inherit.sh
shopt -s localvar_inherit       # localvar_inheritをオンに

foo() {
  local aaa=3   # fooでローカル変数aaaを定義
  bar
}

bar() {
  local aaa     # barでもaaaを定義。値は代入しない
  echo $aaa     # aaaの値は？
}

foo
$ bash ./inherit.sh
3
```

ダイナミックスコープと違い、同じ変数を参照するわけではありません。次のように、barでaaaの値を変更しても、fooのaaaの値は変わりません。

```bash
$ cat inherit.sh
shopt -s localvar_inherit

foo() {
  local aaa=3
  bar
  echo $aaa     # barを呼び出した後でaaaの値は？
}

bar() {
  local aaa
  aaa=5         # barでaaaに5を代入
}

foo
$ bash ./inherit.sh
3
```

## 用途

さて、これをどういうところで使うと便利でしょうか。

普通の変数の値であれば、引数などで渡せば十分です。ただし、配列は引数などでは渡しづらいので、localvar_inheritを使って呼び出し先にコピーするのが便利そうです。
ruby2.6 catch up

ref: https://www.ruby-lang.org/ja/news/2018/12/25/ruby-2-6-0-released/



## outline
- Experimental
- New feature
- Performance improvement
- Remarkable change from 2.5

## Experimental
### JIT compiler
Try later
https://bugs.ruby-lang.org/projects/ruby/wiki/MJIT#MJIT-organization
https://bugs.ruby-lang.org/projects/ruby/wiki/MJIT#Basic-usage
https://medium.com/@k0kubun/ruby-2-6-jit-progress-and-future-84e0a830ecbf
### RubyVM::AbstractSyntaxTree
Try later
## New feature
### endless range
```
p Time.now.. # it generate range obj!

# It doesnot work as expected.
# With ActiveRecord,
User.where(created_at: Time.current..).explain
#=> EXPLAIN for: SELECT "users".* FROM "users" WHERE "users"."created_at" BETWEEN ? AND ? [["created_at", "2019-01-11 12:45:26.755286"], ["created_at", nil]]

# Because mysql interprets that between 2019/01/11 and null fits nothing
```
### new method in Enumerable
New methods added.
- Enumerable#chain
- Enumerator#+

Enumerable#chain connect enumerable in series

```
(1..3).chain(4..6).each { |i| p i }
# 123456
```

Enumerator#+ connect enumerators in series

```
(3.times + (4..6)).map { |i| i * 2 }
#=> [0, 2, 4, 8, 10, 12]
```

### proc like composite function
This is smart syntax as if real mathematic!

```
f = ->(x) { x + 2 }
g = ->(y) { y * 3 }
(f << g).call 4
#=> 14
```

## Performance improvement
Why $SAFE changing cause Proc#call speed up?
Ill Examine later.

What is theap?
Memory manager of short life object

What is Fiber?
Context changer

## Remarkable change from 2.5
Bundler as default gem :tada: :tada: 
$SAFE will treated as global

## setup
```
% rbenv install -l | grep 2.6.0
2.6.0-dev
2.6.0-preview1
2.6.0-preview2
% cd ~/.rbenv/plugins/ruby-build
% git pull
% rbenv install 2.6.0
% cd; mkdir ruby260; cd ruby260
% rbenv local 2.6.0
% ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547)
```
undefined symbols for architecture arm64のエラー

UnityでiOSアプリを開発している時、
ある日突然実機ビルドができなくなりました。

エラーの内容は
`undefined symbols for architecture arm64`

スクリプトがおかしいのかとあれこれ調べましたが結局、

Xcodeの`Clean Build Folder`でCleanしたらあっさりビルドできました。

`Product` -> `Clean Build Folder`

原因不明の時はとりあえずCleanしてみるのはあり。
virtualenvwrapper_lazy.sh: No such file or directory

virtualenvをuninstallした後でterminalを開くたびに

```

bash: /usr/share/virtualenvwrapper/virtualenvwrapper_lazy.sh: No such file or directory.
```
と言われるようになってしまったので，消し方メモ

#消し方

.bashrcを弄ろうとも考えたが，どうやら/usr/share/bash-completion/bash_completionにエラーの原因が書いてあるらしく，ちょっと長かったので断念

今回はvirtualenvwrapperのみを再インストール&再アンインストールしたら何故かエラーが消えました

```

sudo apt-get install virtualenvwrapper
sudo apt-get purge virtualenvwrapper
```

何故なのか分からないので同じエラーを出そうと頑張ってみたものの現れず，再現性が取れてませんので，参考程度にどうぞ．
javascriptの勉強の仕方

#はじめに
昨今は全てjavascriptで実装できるような世の中になりました。
初学者からすると一体どこから手をつけていいのか、全体がどのようになっているのか全くない分からないというのはごく普通のことかと思います。

そんなに精通しているわけではないですが「こんな感じで勉強したらどうだろうか」程度でロードマップを記載します。

#事前知識
ざっくりとしたjavascriptの歴史を知って起きましょう。
Ajaxが半端なくて、node.jsが出てきて、仮想DOMが出てきて、フレームワークが出てきたって感じです。

Javascriptの歴史について
https://qiita.com/a_rcsin/items/0a3c8c98c8d703c49a22

仮想DOMについて
https://qiita.com/risagon/items/019942c60e9c3e6c05a5

#勉強の仕方
###ステップ1　全体像を理解しよう
本を1冊読むのが手取り早いです。
「React，Angular，Vue.js，React Nativeを使って学ぶ はじめてのフロントエンド開発」
https://amzn.to/2H41rME

※javascriptライブラリはこれだけあるので
Awesome JavaScript : 素晴らしい JavaScript のライブラリ・リソースの数々
https://qiita.com/hatai/items/5bf899bfe8f5d86d2096


###ステップ2　javascript言語について勉強しよう
1冊本を読んで最低限の文法を勉強しましょう。

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」
https://amzn.to/2FhY4jq

###ステップ3　node.jsについて勉強しよう

Node.jsとは何かを下記で理解してこちらも本１冊読みましょう。

Node.jsを学ぶ中で必ず押さえておきたいこと
https://qiita.com/i-tanaka730/items/79e8e2c3ceb2bde51436

Node.js超入門[第2版]
https://amzn.to/2FoK5Zt


###ステップ4 各種フレームワークについて勉強しよう

3大フレームワークとしてVue,Anguler,Reactがあります。
一般に開発元がAngulerはGoogle、ReactはFacebook、Vueはサードパーティなので、好き嫌いに応じて触ってみましょう。
書籍が充実してきたので本買って読んではいかがでしょうか。

Vue.js
「基礎から学ぶ Vue.js 」
https://amzn.to/2AIfvFV

Anguler
「Angularアプリケーションプログラミング」
https://amzn.to/2QCQyB6

React
「いまどきのJSプログラマーのための Node.jsとReactアプリケーション開発テクニック」
https://amzn.to/2QBVBl7


###ステップ5　webだけでなくスマホアプリも作ってみよう
React Nativeで楽に作るスマホアプリ開発入門（基本編）
https://qiita.com/teradonburi/items/355a20e6d32bb719ef76

React Native+Expoではじめるスマホアプリ開発 ~JavaScriptによるアプリ構築の実際~
https://amzn.to/2D3TVNJ

#終わりに
今後のシステム開発に関してjavascriptは欠かせないものなので、終わりなき旅を楽しみましょう...

【参考】2018年の最先端フロントエンドエンジニアになろう
https://qiita.com/rana_kualu/items/5986ceab8fd4e353de1b
【SEO対策】上位ページのクローリング＋形態素分析するwebサイトを作ってみた

## SEO対策はタグの中身が大切らしい
SEO対策は色々あるけど `title` `h1` `h2` あたりに何を入れるかが大切らしい。。。
ということで上位ページクローリングしてみました！

## できたもの
**[私もSEO](https://seo.gogomethod.be/)**

- キーワードに関して各タグでどの単語がよく使われているかをランキング化
- ランキング方法は上位ページに出てきた単語ほど重みをつけて集計
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198985/077f96be-569f-aee4-50d3-3595226e81a3.png)

## 最初の設計
- CI/CDを作って開発を早くする
- S3にhtml直置きで簡単にwebサイト化
- `api gateway` 経由で `AWS lambda` を読んでサクッと結果を返す
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198985/5b4afd03-4226-e2b8-9c0f-ed5b7892a897.png)

### クローリングlambdaの中身
クローリングは以下のpythonコードを参考にさせていただきました！

- [【Python】SEO対策に使うため上位100サイトをさくっと抽出するツールを作ってみる](https://trend-tracer.com/python-seo/)
- [Google検索順位チェック用のSEOツールをPythonで自作して自動化する](https://jitekineko.com/tips-python-seo-search/)

また単語を取りたいので以下のサイトを参考に `janome` を使用
[Python初心者が1時間以内にjanomeで形態素解析できた方法](https://qiita.com/d-cabj/items/d934eb87e3012a02e23a)

### 結果api gateway時間短すぎて死亡
そもそもapiってそんなに待つものじゃない。。。

- クローリング＋形態素分析にかかる時間10分なので今のlambdaなら大丈夫
- しかし `api gateway` は30秒ぐらいしか待ってくれない＝＞死亡

## 次の設計図
- `DynamoDB` にキーワードを格納する `キーワード入れるlambda` を作成
- 格納されたらイベント発火で `クローリングlambda` を起動
- `クローリングlambda` は結果を `DynamoDB` に格納
- 再度同じキーワードでみに行くと結果が見れる（ある程度時間が経ったら更新）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/198985/6561e934-1975-c411-15a7-2cc4d4deb3a8.png)

### キーワード入れるlambdaの中身
- まずはじめに１時間以内に更新された結果がないか確認
- 結果がない場合はkeywordを新規レコードとして追加

```python:get_result_or_put_keyword.py
dynamoDB = boto3.resource("dynamodb")
table = dynamoDB.Table({{TABLE_NAME}})  # DynamoDBのテーブル名

result = table.scan(
    FilterExpression=Key('keyword').eq(search_url_keyword)
)["Items"]

if len(result) == 1:
    if "scantime" in result[0].keys():
        # １時間以内に更新されたデータなら使う
        if datetime.now() - datetime.strptime(result[0]["scantime"], '%Y-%m-%d %H:%M:%S') < timedelta(hours=1):
            if "result" in result[0].keys():
                return {
                    'statusCode': 200,
                    'body': result[0]['result']
                }

# 使える結果がない場合はdynamodbにkeywordのレコードを入れる
param = {
    "keyword": search_url_keyword,
    "scantime": now.strftime("%Y-%m-%d %H:%M:%S"),
    "status": 0
}

# DynamoDBへのPut処理実行
table.put_item(
    Item=param
)
print("now searching ...")
return {
    'statusCode': 200,
    'body': "now searching ..."
}
```

### DynamoDBから並列でlambdaを呼び出せず死亡
- 一つだとうまく行くが同じタイミングでいくつかキーワードを入れると処理しきれない
- streaming処理的に `並列lambda` はNGな感じなのかもしれない。。。

## 最終設計図
- streamingで呼び出される `起動lambda` を追加
- 一度に大量に来てもさばけるようになった！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198985/6ec19c70-f677-18e6-5e78-0a6c2afb2e9a.png)

## 肝心のSEO対策は進まず...
最初はクローリングしてSEOに活かそうとしていたのにいつの間にかハマっていたパターン。。。
肝心のSEO対策は進んでいないのでこれからやろうと思います笑
今回SEO対策を考えるきっかけとなったサイト
 **[私もネイル](https://nail.gogomethod.be/)** 
もよろしくおねがいします！
プログラマが知っているとよい設計指針（２）形の設計指針

形の設計指針は、次の８つの項目を考えてきた。

Hazop Safety and Security p.96
https://www.slideshare.net/kaizenjapan/hazop-safety-and-security-at-fukui-201712

<img width="758" alt="figpri.png" src="https://qiita-image-store.s3.amazonaws.com/0/51423/9f4e0d55-13f3-9cae-9cc5-26c0be95f239.png">

| 設計指針 | 要点 |
|:--|:--|
| 単純(simple) | 対称、均衡、調和等で実現 |
| 対称(symmetry) | 方向と時間を考慮 |
| 均衡(balance) | 量と質を考慮 |
| 比率(proportion) | 基準点との比較 |
| 統一と変化(unify) | 変更を想定する |
| 調和（harmony) | 空間的分布の比率 |
| 調子（rhythm) | 時間における比率の変化 |
| 強調(accent) | 優先順位づけ |

共用設計(ユニバーサルデザイン)

| 共用設計の7原則 | Hazopで検討する評価軸 |
|:--|:--|
| 1.どんな人でも公平に使える | 光，音，大きさ，力 |
| 2.使う上で自由度が高い | 選択可能（時間，左右，精度） |
| 3.使い方が簡単で、すぐに分かる | 理解性（光，音がない場合でも） |
| 4.必要な情報がすぐに分かる | 情報提供（光，音以外の方法も） |
| 5.うっかりミスが危険につながらない | 操作の外れを網羅 |
| 6.身体への負担がかかりづらい（弱い力でも使える） | 力，電磁力 |
| 7.接近や利用のための十分な大きさと空間を確保する | 距離、大きさ |

２つの設計指針の関係の案を記述する。

| 共用設計の7原則 | Hazopで検討する評価軸 | 形の設計指針できよする事項 |
|:--|:--|:--|
| 1.どんな人でも公平に使える | 光，音，大きさ，力 | 単純(simple), 対称(symmetry), 均衡(balance) |
| 2.使う上で自由度が高い | 選択可能（時間，左右，精度） | 単純(simple), 対称(symmetry), 均衡(balance) |
| 3.使い方が簡単で、すぐに分かる | 理解性（光，音がない場合でも） | 単純(simple), 対称(symmetry), 比率(proportion), 強調(accent) |
| 4.必要な情報がすぐに分かる | 情報提供（光，音以外の方法も） | 単純(simple), 対称(symmetry), 調和（harmony), 強調(accent) |
| 5.うっかりミスが危険につながらない | 操作の外れを網羅 | 単純(simple), 強調(accent), 統一と変化(unify) |
| 6.身体への負担がかかりづらい（弱い力でも使える） | 力，電磁力 | 単純(simple), 調子（rhythm), 統一と変化(unify) |
| 7.接近や利用のための十分な大きさと空間を確保する | 距離、大きさ | 単純(simple), 統一と変化(unify) |

商品・サービスによって対応する事項が異なるかもしれない。

## Web
例えば、Webで緊急通報するシステムを考えてみよう。

単純なWebでなければ、どんな人でも使えるとは限らない。
単純なWebであれば、使う人が自由に使う、使わないを考えることができる。
単純なWebであれば、使い方も簡単。
単純なWebであれば、必要な情報がすぐに分かる。
単純なWebであれば、うっかりミスの可能性を小さくできるかもしれない。（設計による）
単純なWebであれば、身体への負担がかからないように設計できるかもしれない。
単純なWebであれば、空間をおおきく設計できる。

## コード
画面だけでなく、ソースコードに適用してもよい。

単純なコードでなければ、どんな人が使えるとは限らない。
単純なコードであれば、使う人が自由に使える。
単純なコードであれば、使い方も簡単。
単純なコードであれば、必要な情報がすぐに分かる。
単純なコードであれば、うっかりミスの可能性を減らせるかもしれない。
単純なコードであれば、身体への負担がかからないかもしれない。（昔は、ソースコードを印刷してもってあるいていた）
単純なコードであれば、空間をおおきく利用できる。

# 参考文献(reference)
プログラマが知っているとよい設計指針（１）共用品設計(universal design)
https://qiita.com/kaizen_nagoya/items/0fc20cd873ed0132efa6

# 文書履歴(document history)
ver. 0.01 初稿 20190111
ver. 0.01 初稿 　 20230526
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
@ConditionalOnExpressionとSpELの正規表現でbeanを切り替える

たとえば、spring-bootのプロパティファイルの値に基づいて登録されるbeanを切り替えたい、とする。加えて、そのプロパティ値がある正規表現にマッチした場合に応じて、登録されるbeanを切り替えたい。

この場合は```@ConditionalOnExpression```のSpELで正規表現を使用する。

# ソースコード
## プロパティファイル
いま、あるプロパティ値が```v0001```から```v0004```を取り得るとする。

```yml:src/main/resources/application.yml
oncondition:
#  value: v0001
#  value: v0002
#  value: v0003
  value: v0004
```

このとき、```v0001```から```v0003```の場合と、```v0004```の場合で、beanを切り替えたい、とする。

## 切り替えられるクラス
適当なinterfaceを作る。

```java
public interface ISample {
    String value();
}
```

```java
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;

@Component
@ConditionalOnExpression("#{'${oncondition.value}' matches 'v000[123]'}")
public class Value123 implements ISample {
    @Override
    public String value() {
        return "value123";
    }
}
```

```java
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;

@Component
@ConditionalOnExpression("#{'${oncondition.value}' matches 'v0004'}")
public class Value4 implements ISample {
    @Override
    public String value() {
        return "value4";
    }
}
```

```@ConditionalOnExpression```はSpELがマッチする場合に有効となる。ここでは```${oncondition.value}```でプロパティを参照し、正規表現```matches 'v000[123]'```を記述している。これによって、```oncondition.value```が```v0001```,```v0002```,```v0003```の場合にこのクラスが有効になる。

## 実行
最後に確認するための起動用クラス。

```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App implements CommandLineRunner {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Autowired
    ISample hoge;
    
    @Override
    public void run(String... args) throws Exception {
        System.out.println(hoge.value());
    }
}
```
今月の「認識相違に迫る」 Vol.1

私の今までの考えとしては、
「JavaがわかればPythonでもPHPでも多分できる。ググれば。」

という考え方ですが、どうもその考えに共感する人とそうでない人が極端に分かれるのです。

どういう認識差異なのだろうといつも疑問だったのですが、
最近ようやく理解できるようになってきました。

〇〇言語が書ける。　という定義が人によって大きく異なるのだなということが・・・！

以下、難易度順に並べると、

レベル１ 〇〇言語が書ける = 基本構文（if, for）が書ける
レベル2 〇〇言語が書ける = 基本的な言語特性（オブジェクト指向？関数型？）を使って書ける
レベル3 〇〇言語が書ける = フレームワークやその言語の本質を知っている
レベル4 〇〇言語が書ける = レベル3を踏まえた上で、ロジックを組むことができる　（セオリーやTips的なことを知っている。使える。）

レベル1の認識の人間と、レベル4の認識の人間が話せば、
そりゃあ共感にはならないのだなと思いました。

ついこの間までは、私はレベル1（ちょっとだけ2）の人間だったのですが、
こうやってまとめてみたことで、
あーーーーー、そういうことを言いたかったのね。と思うわけです。

あとは、学習コストが高い = 時間がかかる。　ということだと思いますが、
世の中には、時間をかけても解決できない問題がたくさんあるのに、
時間をかけるだけで自分のものにできるなんて、
なんて楽なんだ・・・と思うわけです。

私は、学生時代にC++で大規模アプリケーションを作った上で、
Javaを使った業務をしているので、
Javaのどんな構文を見ても、
「あーはいはい、C++でいうところの〇〇ね」みたいな感じで受け入れることができたわけですが、

C（初めて勉強した言語） → C++　のときは、
もうすべてが初めてで、混乱してそれはそれはワニワニパニックだったことを思い出します。
（特に、初のオブジェクト指向なので。）

仕事では、私は新人の教育担当なので、
新人を教育するためにも、初心を振り返った3連休前の金曜日でした。

今回の教訓：
　・他の人の目線で考えてどういう意味なのかを探ると意外と発見がある。
　・新人を教育する上で、大切なのは壁に当たらせること。
　（私がC → C++のときに経験した巨大な壁を新人にも与えること。）

以上です。
Elixir＆Phoenix学習中に気になったCSRFのコト

Elixir＆Phoenixの学習中で、分からない言葉は調べながら進めています。
なので、備忘録的なものです。

環境
MacOS Ⅹ
Elixir 1.7.4
Poenix 1.4.0


## Excelから関数型言語マスターシリーズ6回目をやってみた

@piacere_ex さんの「Excelから関数型言語マスター」シリーズを5回目までやったので
いよいよ[「Excelから関数型言語マスター6回目： Vue.js＋内部API（表示編）」](https://qiita.com/piacere_ex/items/50d847170291c41fef64)
をやってみました。

流れはpiacere_exさんのページを見て進めればいいから、ここには書かない。

順に進めて行けば大丈夫。
1~5回目までをやった時にも思ったけど、APIと合わせるとこんなに色々できるってすごい…


## 気になったコト

APIでデータ投入のところに出てくるけど、今回は一旦外しておく。
と言うコレ。


```router.ex
plug :protect_from_forgery
```

forgery？？？
「偽造」って、なんだかただ事じゃない感…


CSRFの保護を有効にするPlugらしいと言うのは分かった。
[phoenixのドキュメント](https://hexdocs.pm/phoenix/Phoenix.Controller.html#protect_from_forgery/2)にも書いてある。

と言われても、CSRFって一体なにものなのか…
偽造されない為に保護するものなのはわかるけど、一体なんなのだろう。

## CSRFって？

Cross-Site Request Forgery頭文字を取ってCSRF。
クロスサイト・リクエスト・フォジェリーと読むらしい。

>リクエスト強要（CSRF：Cross-site Request Forgery）とは、別のサイトに用意したコンテンツ上の罠のリンクを踏ませること等をきっかけとして、インターネットショッピングの最終決済や退会等Webアプリケーションの重要な処理を呼び出すようユーザを誘導する攻撃である。。
（引用元：[IPA 独立行政法人情報処理推進機構](https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/301.html)）


怖い怖い。
対策しないとダメなんじゃないの？
と思ったけど

piacere_exさんの記事の中にも紹介されている↓の記事を読むとわかる
http://watanabe-tsuyoshi.hatenablog.com/entry/2015/03/04/123649

ログインが必要な状況で、その中に個人情報など含まれている場合に困るということ。
基本的にログインしている状態以外のところにこの攻撃をしてもあまり意味はないらしい。
　

そもそも、今回このままサービスとして公開する訳ではないし…

だからこの部分に時間をかけるよりは、実際に動くものを作れるんだ。
と言うのが簡単にできる体験の方が重要なのでしょうね。
動いた！できた！って、分かるとより深いところまで知ってみたくなるもの。
　

対策をするのではなく、コメントアウトして機能を無効化した理由はそこかな？

まぁ、「本筋から外れるから…」と書いていらっしゃるわけですし♪



## 実際の対策は

対策方法はドキュメントに書いてあるから、実際に必要な時はここ見て作る。
https://hexdocs.pm/plug/1.7.0/Plug.CSRFProtection.html

ここ試してみたら、また書こう。
　　

それにしても、プログラミングってただ書けるようになればいいだけじゃなく、情報セキュリティ対策も知らないといけないよね…
知らなくてごめんなさい。
って思った。

そんなの当たり前でしょ！
って人が多いのかもしれないけど…
初心者すぎて「言語を覚える」ってコトが優先になってて、その他にもっともっと必要ないろんなコトが抜けてた。
この辺も勉強しないとなぁ。
　

実際に手を動かしてみて、なんでこうなのか。
なんでこれが必要なのかって、調べて理解していくコトって大切ね。
Text Mesh Proで簡体中国語と韓国語を使う

# はじめに
趣味でYouTubeLiveのコメントを取得して、Unityで表示するアセットを作った。
「Text Mesh Proつかっていろいろ演出できるじゃん！」と思って、いろいろなVTuberさんの配信をサンプルとして取得していたのだが、結構海外の人も見ている模様。
特に韓国の方は多そう。
Text Mesh Proで日本語を扱う記事は多かったが、中国語や韓国語はﾁｮｯﾄﾜｶﾗﾅｲ・・

調べました。
## 環境
Unity 2018.2.11f1
NotoSansCJKsc (簡体字 Simplified Chinese)
NotoSansCJKkr (ハングル)

## フォントアセットを作る
Unityのツールバーから、
Window -> TextMeshPro -> Font Asset Creator
で作成できる。

### 簡体中国語
たまたま中国語が読めたので、中国サイトをいくつか調べてみたところ、
中国の方はUnicodeの中国語領域である0x4E00 ~ 0x9FBFを指定してフォントアセットを作っていた。

```text:コピー用
4E00-9FBF
```

十進数にすると19968-40895なので約2万文字。
この量は8192x8192じゃないと収まらない。

![sctextmeshpro.PNG](https://qiita-image-store.s3.amazonaws.com/0/45094/59b36295-25ba-9c67-cbe1-645176a15083.png)

できた。すごい量・・・。

### 韓国語
韓国語って文字少ないイメージあるけど、どうなんだろう。
韓国語は読めなかった。
Unicodeの領域を調べよう。

メモ帳を起動してIMEPadを開いてみた。
NotoSansCJKkrフォントで使えるよう文字を調べたいので、右上でインストールしておいたフォントに切り替える。

<img src="https://qiita-image-store.s3.amazonaws.com/0/45094/3c071a84-11df-c9fc-39cc-703553666cbc.png" width=75%>

一部非対応っぽい文字を除いて、母音や子音を含めると、
どうやら
0x1100-0x115E
0x1161-0x11F0
0x3131-0x318E
0xAC00-0xD7A3
0xA960-0xA97C
0xD7B0-0xD7C6
0xD7CB-0xD7FB

```text:コピー用
1100-115E,1161-11F0,3131-318E,AC00-D7A3,A960-A97C,D7B0-D7C6,D7CB-D7FB
```

が範囲のようだ。


多くない？

0xAC00-0xD7A3は44032-55203だから一万文字超えてる。

予想より多かったが、8192x4096でいけそう。
感がそう告げている。

![krtextmeshpro.PNG](https://qiita-image-store.s3.amazonaws.com/0/45094/7056651b-6ff6-4e86-735a-8ad2b43ea9d0.png)


できた。
これもすごい量だ・・・。

## 使用してみる
とにかく、出来たし使ってみよう。
### 準備
フォントアセットが複数あるので、一つのアセットに紐づけを行う。
Fallback Font Assetsのリストに追加することで、使用しているフォントアセットで見つからないフォントがあった場合、リストの中から探してくれるみたい。
<img src="https://qiita-image-store.s3.amazonaws.com/0/45094/e2e8ffa1-eadf-1b85-8d53-27b320713980.png" width=50%>

### 確認

最近中国語圏で熱いと噂の神楽めあちゃんがちょうど配信していたのでテスト
<img src="https://qiita-image-store.s3.amazonaws.com/0/45094/c1a0aa1c-814e-176f-307a-9696425c5644.gif" width=50%>
韓国の方がwebカメラ配信していたのでテスト（なに書いてあるかわからない）
<img src="https://qiita-image-store.s3.amazonaws.com/0/45094/fbff18db-6a8c-4d17-7ff2-c5183a2980a8.gif" width=50%>

だいたい大丈夫そう。
​絵文字は対応しきれていないから表示できていないみたい。🥁
Amazon EKS で構築したクラスタを kubeconfig に設定

既に構築した EKS クラスタを kubeconfig に設定する。

## kubeconfig 設定

aws-cli 1.16.18 以上をインストールしておけば、`aws eks update-kubeconfig` コマンドで設定できる。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started.html

```
$ aws eks update-kubeconfig --name EKS_CLUSTER_NAME
```

`~/.kube/config` にクラスタの設定が追加される。

## kubectl 実行時

設定後、kubectl で対象クラスタにアクセスする際は、aws-iam-authenticator コマンドが必要となるので、無ければインストールしておく。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/configure-kubectl.html

プラットフォーム毎のバイナリが用意されているので、curl 等でダウンロードする。
Flutterでプログラムからアプリを終了する

`flutter/services.dart`をimportすると使える[SystemNavigator.pop](https://docs.flutter.io/flutter/services/SystemNavigator/pop.html)を呼び出すとアプリを終了して前の画面に戻ります。

`dart:io`の`exit()`を使う方法もありますが、こちらは突然Dartプロセスが終了したようになって画面が突然消えてしまう上、Activity履歴にゴミが残ってしまうので使わないようにしましょう。
Ubuntu16.04においてGromacsでCUDAを使用するための準備

# 行ったこと
###パッケージの準備

- openmpi1.10.2
- fftw-3.3.4
- cuda8.0

###インストール
- CMakeの再インストール
- 必要なコンパイラをインストール
- OpenMPIのインストール
- FFTWのインストール
- CUDAのインストール


# CMakeの再インストール

- CMakeをアップデートして使用した場合に問題が起きる可能性があるとのことで、再インストールしておいた.
 
 `sudo apt remove cmake`
 `sudo apt install cmake`


# OpenMPのインストール
###不足しているコンパイラを揃える. aptでインストールして問題ない.
- OpenMPIではGCC,G++,GFortranのコンパイラが必要である。私は新しいPCで環境構築したのでGFortranがインストールされていなかった.

`sudo apt install gfortran`
 

### OpenMPI

- サイトからopenmpi1.10.2のパッケージをダウンロードして解凍.
- aptでインストールする場合,オプションとバージョンに注意する.
- 執筆時点で最新のfftw3.3.8はGromacs-2018に対応していないのか動かなかった.
- 適当なフォルダに移動し以下の通りオプション指定する.
- 長いのでのんびり待つ．

`cd openmpi-1.10.2`
`./configure --enable-static --prefix=/usr/lib/openmpi CC=gcc CXX=g++ F77=gfortran FC=gfortran`
`sudo make`
`sudo make install`
`sudo make clean`



# FFTWのインストール

- 同様にサイトからfftw-3.3.4のパッケージをダウンロードして解凍.
    - fftw3-3をaptインストールも可．

### コンパイラ

`cd fftw-3.3.4`
`export LD_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/5.4.0:$LD_LIBRARY_PATH`
`export LD_LIBRARY_PATH=/usr/lib/openmpi/lib:$LD_LIBRARY_PATH`
`./configure --prefix=/work/app/fftw-3.3.4.openmpi.gcc CC=gcc CXX=g++ F77=gfortran FC=gfortran --enable-mpi --enable-threads --enable-sse2 --enable-openmp --enable-static --enable-shared --with-g77-wrappers MPICC=/home/owner/openmpi-3.1.0/ompi/tools/wrappers/mpicc LDFLAGS=-L/usr/lib/openmpi/lib CPPFLAGS=-I/usr/lib/openmpi/include`
- 上記のディレクトリには仮ユーザ名`owner`が入っているので各々のユーザ名に書き換える. 

`sudo make`
`sudo make install`

### FFTW

`./configure --prefix=/work/app/fftw-3.3.4.openmpi.gcc CC=gcc CXX=g++ F77=gfortran FC=gfortran --enable-mpi --enable-threads --enable-sse2 --enable-openmp --enable-static --enable-shared --with-g77-wrappers MPICC=/usr/bin/mpicc LDFLAGS=-L/usr/lib/openmpi/lib CPPFLAGS=-I/usr/lib/openmpi/include --enable-single`

`sudo make`
`sudo make install`


# CUDAのインストール

- 同様にサイトからCUDA8.0のパッケージをダウンロードして解凍.

`sudo sh cuda_8.0.61_375.26_linux.run`

- Gromacsが対応しているCUDAはCUDA8以下であり,最新のCUDAではGromacsをインストールすることができなかった.


# Gromacsのインストール

- 適当なフォルダに移動しオプション指定する.　新しいフォルダを作成してその中で作業する.

`cd gromacs-2018`
`cd build
`export LDFLAGS="-L/work/app/fftw-3.3.4.openmpi.gcc/lib"`
`export CPPFLAGS="-I/work/app/fftw-3.3.4.openmpi.gcc/include"`
`export LD_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/5.4.0:$LD_LIBRARY_PATH`
`export LD_LIBRARY_PATH=/usr/lib/openmpi/lib:$LD_LIBRARY_PATH`
`sudo cmake ../ -DCMAKE_C_COMPILER=/usr/lib/openmpi/bin/mpicc -DCMAKE_CXX_COMPILER=/usr/lib/openmpi/bin/mpicxx -DGMX_THREAD_MPI=ON -DGMX_SIMD=AVX_256 -DGMX_DOUBLE=OFF -DGMX_OPENMP=ON -DGMX_GPU=ON -DCMAKE_INSTALL_PREFIX=/work/app/gromacs-2018.openmpi.gcc.gpu -DBUILD_SHARED_LIBS=OFF -DGMX_PREFER_STATIC_LIBS=ON -DGMX_FFT_LIBRARY=FFTW3 -DCMAKE_PREFIX_PATH=/work/app/fftw-3.3.4.openmpi.gcc`


- か，
cmake .. -DGMX_BUILD_OWN_FFTW=ON -DREGRESSIONTEST_DOWNLOAD=ON -DGMX_GPU=ON -DGMX_THREAD_MPI=ON -DCMAKE_CXX_COMPILER=/usr/lib/openmpi/bin/mpicxx -DGMX_OPENMP=ON -DCMAKE_C_COMPILER=/usr/lib/openmpi/bin/mpicc



- OpenMPIとCUDAを設定しGromacsをインストールし、パスを通した.
 
`sudo make`
`sudo make install`
`sudo make clean`


# 気をつけたこと

- パスは自分の環境において正しいか.
- バージョンがGromacsと合っているか.
- コマンドをペーストする際に改行で途切れていないか.
実践！Firebase Authでソーシャルログインとユーザー管理



**※目次のみです。そのうち中身追加します。**

## 事前準備

**スキルセット最低ライン**
jQueryが使えたり、ajaxが何となく分かる人向け

**セキュリティリスク**
ある程度Firebase(Google)任せになるので、深い知識は必要としないが潜在的なリスクがあるので、勉強するのに越したことはない。

**メリット**
認証のサーバー側セキュリティをFB任せにできる。
フロントエンドだけで会員登録&ページ認証ができる

**デメリット**
セキュリティポリシーがある会社は使えないかも。

基本はFIREBASEのドキュメントにすべて書いてあるので、それに沿って行います。

## Fierbase環境設定
[※Firebaseドキュメントどおりに勧めばOK](https://firebase.google.com/docs/web/setup)
1. [Firebaseコンソールに移動](https://console.firebase.google.com/u/0/?hl=ja)
1. プロジェクトを追加する
1. Authenticationに移動し、ログイン方法を「匿名を有効」に設定。※匿名以外は後記
1. Databaseに移動して、Cloud Firestoreで「データベースを作成」する。※テストモードでいいです。
1. 公開するサイトがなければHostingもinitに沿って作成

## 開発環境設定
[※Firebaseドキュメントどおりに勧めばOK](https://firebase.google.com/docs/auth/web/start)
※ FWとの連携する場合は後記

1. index.htmlを作成
1. FirebaseAuthenticationのWeb要設定を追加
1. 実行・確認

## 閲覧者を匿名ユーザー化しよう
[※Firebaseドキュメントどおりに勧めばOK](https://firebase.google.com/docs/auth/web/anonymous-auth?authuser=0)
1. 匿名ユーザーを作成
1. 実行・確認
1. ユーザーを削除しよう

------ ここまではドキュメント読めばOK

## パスワード認証で匿名ユーザーの永久化しよう

ここまでの段階で、ページにアクセスした閲覧者には、匿名ユーザーのUIDが振られています。[詳しくはこちら](https://firebase.google.com/docs/auth/users?authuser=0#auth_tokens)

1. メール・パスワードの入力項目を作成
1. サインアップする
2. メール認証する

## ソーシャルログインでアカウントとリンクしよう
1. アカウント管理項目を追加
1. 各サービスのデベロッパーIDを取得
1. アカウントリンクする
1. アカウントリンクを外す
1. 匿名からSNS認証への永久化

## ユーザー情報の管理しよう
1. Authが保持できる情報
1. ソーシャルから取得できる情報

## FirebaseStoreで独自にユーザー情報の管理しよう
1. FirebaseStoreでAuth以上のユーザー情報を登録する
1. セキュリティルールを設定する
1. Storageで画像を管理
1. FireStoreと紐付いた情報と一緒にユーザーを削除しよう

## その他
1. vueでの連携
1. laravelでの連携
1. 匿名ユーザーのバッチ削除
1. push通知使ってみる
1. Analytics連携
【Python】「rm -rf /」ドッキリ


# 作ったもの
![rm.gif](https://qiita-image-store.s3.amazonaws.com/0/231104/22435215-e7a0-d6b7-98ed-d3b7d1ee217d.gif)
冒頭のプログラム実行以降は，全て自動で行っています。


# プログラム
## ソースコード全体
https://github.com/derodero24/MacDestroyer

## マウス操作
本物のターミナルを開いている感を出すために，dockのアイコンまで移動します。もちろん本当にクリックはしません。その後，開いた疑似ターミナル画面まで動きます。

```py
import pyautogui as pgui
from time import sleep

def cursor_animation():
    pgui.moveTo(1500, 480, duration=1)  # dock
    pgui.moveTo(1420, 480, duration=1)  # ターミナルアイコン
    sleep(0.6)
    pgui.moveTo(100, 300, duration=1)   # ターミナル画面
```

## 疑似ターミナル
できるだけ自分のターミナルに似せました。

```py
import tkinter as tk

class Terminal(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('ターミナル ー -bash ー 80×24')
        self.configure(width=750, height=450)

        self.wtext = tk.Text(self,
                             width=50, height=40,
                             padx=10, pady=8,
                             bg='#313131', fg='#ffffff',
                             wrap=tk.CHAR,
                             font=('Osaka', 14))
        self.wtext.place(x=-5, y=-5, width=760, height=460)
        self.wtext.tag_config('prompt', foreground='#00FFFF')
        self.wtext.tag_config('warning', foreground='#E52121')
        self.wtext.tag_config('error', foreground='#E5E500')
```

## コマンドアニメーション
（次に追加する文字列，追加後に待つ時間[msec]，タグ）を返すジェネレータを作成し，それを元にafter()関数で再帰的に追加タイマーを作成します。

```py
def frame_gen(self):
    ''' animation frames '''
    # (text, wait_time, tag)
    frames = (
        ('Last login: Thu Jan 10 12:45:36 on ttys000\n', 1000, ''),
        (f'{os.uname()[1].split(".")[0]}:~ {os.environ["USER"]}$ ', 2000, 'prompt')
    )
    for f in frames:
        yield f

def animation(self):
    ''' タイマー設定 '''
    try:
        next_frame, wait, tag = next(self.frame)
    except:
        return
    last_insert = self.wtext.index(tk.INSERT)
    self.wtext.insert(tk.INSERT, next_frame)
    self.wtext.tag_add(tag, last_insert, tk.INSERT)
    self.wtext.see('end')
    self.after(wait, self.animation)
```


## 備考
使用する際は各パラメータを自分用にカスタマイズする必要があります。
ask-cliを絶対にglobalにいれたくなくてTypeScriptなDocker環境つくった

リポジトリ
https://github.com/shinichi-takahashi/docker-ask-cli-ts

## 背景
- *TypeScriptでつくりたい*
- ask-cliが `~/.ask` を参照するしglobalに入れろって言ってきがち
    - globalにコマンドを絶対に生やしたくない
    - Dockerのglobalで勘弁してやろう...
- 共同開発したい
    - .askを共有していきたい

## 使い方
READMEから転載

最初にやること

```
# Dockerイメージの作成
docker-compose up --build

# アカウント認証
docker-compose run ask-app ask init --no-browser
```

チートシート

```
# デプロイ
docker-compose run ask-app ask deploy

# コンテナに入りたい場合
docker-compose run ask-app sh

# コンテナの破棄
docker-compose down
```

`ask new` を叩く代わりにDockerコンテナ立ち上げることで同等のことを行うイメージで作りました。

## いいことあるの？

### プロジェクト毎に環境を閉じられる

.askをDockerのユーザーホームに追加するので共通なコンテナ使うより煩雑になりづらくした。
git cloneしてdocker-composeをﾎﾟﾁｰするだけでおｋ
（.envで `COMPOSE_PROJECT_NAME` 変更とかはしたほうがいいけど）

### TypeScript -> JavaScriptをhooksで行う

hooksが生えてたので、それを利用してwebpackでトランスパイルをするようにした
当初はホットリロード的なものを実装しようと思ってたけど、必要ないかな？とおもって未実装
書いてて思ったんだけど、 `ask simulate` たたくときとかは必要そうだから以下を参考に今後実装します。
https://qiita.com/yuukive/items/012bdf1b9ff3881546b3#%E5%A4%89%E6%9B%B4%E6%A4%9C%E7%9F%A5%E3%81%97%E3%81%A6%E8%87%AA%E5%8B%95%E3%83%AA%E3%83%AD%E3%83%BC%E3%83%89

## 参考
https://github.com/martindsouza/docker-amazon-ask-cli
【基本情報とかで出るやつ】10進数から2進数への変換をちょっと丁寧に

# はじめに

後回しにしていたけどそろそろ応用情報を取っとこうと思う。
毎回、10進数を2進数に変換するやり方を忘れるのでちょっと深掘りして少しまとめておく。
いま**29.3**歳くらいなのでこれを2進数にしてみよう。**11101.001011...** になる。

# 機械的な計算方法

- 整数部分（29）と小数部分（0.3）は別にして扱う。
  - 整数部分は、2で割って、商と余りを求める。商をさらに2で割って、商と余りを求める。これを商が0になるまで繰り返す。余りを下から順に左から右に並べると2進数での表示になる（図1）。
  - 小数部分は、2を掛けて、積を求める。積の小数部分だけ取り出して、さらに2を掛けて積を求める。これを積が0になるまで繰り返す（0にならずに循環する場合は適当に打ち切る）。積の整数部分を上から順に左から右に並べると2進数での表示になる（図2）。
  - 上からとか下からとかをよく忘れる。

![base_conversion01.png](https://qiita-image-store.s3.amazonaws.com/0/150194/e1a789a3-95c5-dde8-cb4f-f4256c5b242e.png)
... 図1: 整数部分の計算方法

![base_conversion02.png](https://qiita-image-store.s3.amazonaws.com/0/150194/53cc1d3d-3021-4ebd-4089-570498989009.png)
... 図2: 小数部分の計算方法


# こうやっていい根拠


## 整数部分

$a_{i}$は0か1であるとする（というかなる）。
29を2進数で表したいというのは、以下を満たす$a_{i}$を決めたいということだ:

```math
29 \, =  \,\cdots\, + a_{4}2^{4} + a_{3}2^{3} + a_{2}2^{2} + a_{1}2^{1} + a_{0}2^{0}
```

右辺が何項あるのかは現時点では不明である。
ここで、右辺の$a_{0}2^{0}$以外の項をかっこでくくる。あと、$a_{0}2^{0}$ は $a_{0}$ と書くことにする。

```math
29 \, =  \, (\,\cdots\, + a_{4}2^{4} + a_{3}2^{3} + a_{2}2^{2} + a_{1}2^{1}) + a_{0}
```

右辺のかっこから2をくくりだす。それぞれの項の2の指数が1ずつ減る。

```math
29 = (\cdots + a_{4}2^{3} + a_{3}2^{2} + a_{2}2^{1} + a_{1}2^{0}) \times 2 + a_{0}
```

左辺の29という数は、$14 \times 2 + 1$とも書ける。というわけで、

```math
14 \times 2 + 1 = (\cdots + a_{4}2^{3} + a_{3}2^{2} + a_{2}2^{1} + a_{1}2^{0}) \times 2 + a_{0} \tag{1}
```

つまり、$(\cdots + a_{4}2^{3} + a_{3}2^{2} + a_{2}2^{1} + a_{1}2^{0}) = 14$で、また、$a_{0} = 1$ であることがわかる。

同様の計算を繰り返していく:

```math
\begin{align}
14 \,&= \,\,\, \cdots + a_{4}2^{3} + a_{3}2^{2} + a_{2}2^{1} + a_{1}2^{0} \\
14 \,&= \,(\cdots + a_{4}2^{3} + a_{3}2^{2} + a_{2}2^{1}) + a_{1} \\
7 \times 2 + 0 \, &= \,(\cdots + a_{4}2^{2} + a_{3}2^{1} + a_{2}2^{0}) \times 2 + a_{1}
\end{align}
```

つまり、$(\cdots + a_{4}2^{2} + a_{3}2^{1} + a_{2}2^{0}) = 7$で、また、$a_{1} = 0$ であることがわかる。

以下、左辺が0になるまで続ける。

式(1)でやっているのは、上で見た「機械的な計算方法」（図1）の1回目の2割りと同じ。
それで、式(1)の結果として $a_{0} = 1$ になることが分かった。
2進数で表示するときは$a_{0}$が一番右に来るわけなので、
「下の余りから順に左から右に並べる」ということになる。


## 小数部分

$b_{i}$は0か1であるとする。
0.3を2進数で表したいというのは、以下を満たす$b_{i}$を決めたいということだ:

```math
0.3 \,=\, b_{1}2^{-1} + b_{2}2^{-2} + b_{3}2^{-3} + b_{4}2^{-4} + \cdots
```

右辺が何項あるのかは現時点では不明である。
ここで、両辺を2倍する。右辺のそれぞれの項の2の指数が1ずつ増える:

```math
0.6 \,=\, b_{1}2^{0} + b_{2}2^{-1} + b_{3}2^{-2} + b_{4}2^{-3} + \cdots
```

ここで、右辺の$b_{1}2^{0}$以外の項をかっこでくくる。あと、$b_{1}2^{0}$は$b_{1}$と書くことにする。

```math
0.6 \,=\, b_{1} + (b_{2}2^{-1} + b_{3}2^{-2} + b_{4}2^{-3} + \cdots) \tag{2}
```

左辺の整数部分は0である。また、右辺のかっこ内は小数となる。かつ、$b_{i}$は0か1であるという制約から、$b_{1}$は0と決まる。

残った小数について同様の計算を繰り返していく:

```math
\begin{align}
0.6 \,&=\, b_{2}2^{-1} + b_{3}2^{-2} + b_{4}2^{-3} + \cdots \\
1.2 \,&=\, b_{2}2^{0} + b_{3}2^{-1} + b_{4}2^{-2} + \cdots \\
1.2 \,&=\, b_{2} + (b_{3}2^{-1} + b_{4}2^{-2} + \cdots)
\end{align}
```

左辺の整数部分は1である。また、右辺のかっこ内は小数となる。かつ、$b_{i}$は0か1であるという制約から、$b_{2}$は1と決まる。

以下、左辺が0になるまで続ける（循環し始めたらそこらで止める）。

式(2)でやっている操作は、上で見た「機械的な計算方法」（図2）の1回目の2掛けと同じ。
それで、式(2)の結果として $b_{1} = 0$ になることが分かった。
2進数で表示するときは$b_{1}$が（小数点以下の）一番左に来るわけなので、
「上の整数部分から順に左から右に並べる」ということになる。
IFTTT と Zapier の比較。 Zapier は無料ではほとんど使えない。お金が必要。

IFTTT と Zapier の比較。 Zapier はそもそも無料でほぼ使えない。お金が必要。

# Zapier

- 無料では1ヶ月 100 taskまでしか使えない。ほぼ使えないレベル。
- Starter でも 1日あたり100task ぐらいだし、ちょっと辛そう。
- 結論、お金が必要。

![image](https://user-images.githubusercontent.com/13635059/51025620-e53e7500-15cf-11e9-9034-208f040ffbf4.png)

https://zapier.com/app/billing/plans

# OOps

![image](https://user-images.githubusercontent.com/13635059/51025674-0901bb00-15d0-11e9-95ce-03c6d9bdab8a.png)



---

https://twitter.com/YumaInaura

https://github.com/YumaInaura/YumaInaura/issues

https://github.com/YumaInaura/YumaInaura/issues/328








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
[Unity]シンプルな期間限定機能作成(DateTimeの利用メモー)

クライアントのみでの処理
---
**TimeLimit.cs**コンポネント作成


    public class TimeLimit : MonoBehaviour
    {
        /// <summary>
        /// 限定日にち
        /// </summary>
        [SerializeField]
        private LimitedTime limitedtime;
        [SerializeField]
        private GameObject description;
        private void Start()
        {
            //起動時、期間内時チェック
            if (PlayerPrefs.GetString("HasExpired", "false") == "false")
            {
                //期間切れ処理
                if (HasExpired(limitedtime))
                    PlayerPrefs.SetString("HasExpired", "true");
            }
            //期間切れ処理
            if (PlayerPrefs.GetString("HasExpired", "false") == "true")
                description.SetActive(true);
            //期間内処理
            else
                SceneManager.LoadScene("Main");
        }
        /// <summary>
        /// 期間切れかどうかを返す
        /// true:期間切れ、false:期間内
        /// </summary>
        private bool HasExpired(LimitedTime limit)
        {
            //現在の UTC 日時
            var now = DateTime.UtcNow;
            //限定日時取得
            var limitdate = GetDateTime(limit);
            //残り日時処理
            var remaining = limitdate - now;
            //残り日数チェック
            if (remaining.TotalDays < 0)
                return true;
            return false;
        }
        /// <summary>
        /// DateTimeを返す
        /// 日にち範囲外の処理をする。
        /// </summary>
        private DateTime GetDateTime(LimitedTime limit){
            //limit.year年範囲外処理
            var year = Mathf.Clamp(limit.year, 2018, 2028);
            //limit.month月範囲外処理
            var month = Mathf.Clamp(limit.month, 1, 12);
            //limit.month月の日数を取得
            var days = DateTime.DaysInMonth(year, month);
            //日範囲外処理
            var day = Mathf.Clamp(limit.day, 1, days);
            return new DateTime(year, month, day);
        }
    }
    [Serializable]
    public class LimitedTime
    {
        [Range(2019, 2028)]
        public int year;
        [Range(1, 12)]
        public int month;
        [Range(1, 31)]
        public int day;
    }

シーン上GameObject作成し、TimeLimitコンポネントを追加し**Year/Month/Day**を指定。
**Description**には表示させるGameObjectをアタッチ
![1.png](https://qiita-image-store.s3.amazonaws.com/0/159490/28686a68-026e-0d7f-f512-2fb4cc605282.png)
Swift4.2 半角全角数字を漢数字へ変換の話 ?

# Swift4.2 三項演算子ではなくてfor文とif文 ?
&nbsp;


- 目的

> 単純にテーマの通りですが ? 参考サイトでは三項演算子で解決していますが ? 私はそれを少しは理解できますが ? 私は昔ながらのfor文とif文が好きなので変更してみました

こんなヤツ

- １丁目1３6番地 -> 一丁目一三六番地

[「参考サイト」](https://slowlylearner.hateblo.jp/entry/2017/05/29/004223)

```ViewController.swift

//
//  ViewController.swift
//  Hankaku_Zenkaku_Kanjihenkan
//
//  Created by 福田敏一 on 2019/01/11.
//  Copyright © 2019 福田敏一. All rights reserved.
//

//参考サイト https://slowlylearner.hateblo.jp/entry/2017/05/29/004223

import UIKit

class ViewController: UIViewController {
    
    let japaneseNumericalChars : [String : String] = [
        "0": "〇",
        "1": "一",
        "2": "二",
        "3": "三",
        "4": "四",
        "5": "五",
        "6": "六",
        "7": "七",
        "8": "八",
        "9": "九",
        "０": "〇",
        "１": "一",
        "２": "二",
        "３": "三",
        "４": "四",
        "５": "五",
        "６": "六",
        "７": "七",
        "８": "八",
        "９": "九",
        ]
    let stri : String = "１丁目1３6番地"//全角と半角数字が混合している

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        let japaneseChars : Set = Set(japaneseNumericalChars.keys)
        let strArr = stri.map{japaneseChars.contains($0.description)}
        let mapTrue = stri.map{japaneseNumericalChars[$0.description]}
        let stringArray : [String] = stri.map{($0.description)}
//三項演算子ではなくて私の分かりやすいコードで書いてみました
            for i in 0..<stringArray.count {
                if strArr[i] == true {
print("1通過・mapTrue[1] -> \(mapTrue[i]!)")
                } else {
print("3通過・stringArray[i] -> \(stringArray[i])")
                }
            }
        }

}

//実行結果
/*
1通過・mapTrue[1] -> 一
3通過・stringArray[i] -> 丁
3通過・stringArray[i] -> 目
1通過・mapTrue[1] -> 一
1通過・mapTrue[1] -> 三
1通過・mapTrue[1] -> 六
3通過・stringArray[i] -> 番
3通過・stringArray[i] -> 地
*/


```

ここまで
PDF のサイズ、回転を表示 (Python3)

コマンドで表示

```text
$ pdfinfo sample01.pdf 
Producer:       PyPDF2
Tagged:         no
UserProperties: no
Suspects:       no
Form:           none
JavaScript:     no
Pages:          1
Encrypted:      no
Page size:      1190.55 x 841.89 pts
Page rot:       90
File size:      49884 bytes
Optimized:      no
PDF version:    1.3
```

Python で表示

```py:pdf_spec.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	pdf_spec.py
#
#						Jan/11/2019
#
# ------------------------------------------------------------------
import	sys
#
import	PyPDF2
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
file_in = sys.argv[1]
#
sys.stderr.write(file_in + "\n")
#
pdf_first = open(file_in,'rb')
pdf_reader = PyPDF2.PdfFileReader(pdf_first)
page_a = pdf_reader.getPage(0)
print(page_a.mediaBox.lowerLeft)
print(page_a.mediaBox.upperRight)
print(page_a.get('/Rotate'))
#
pdf_first.close()
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行例

```text
$ ./pdf_spec.py sample01.pdf 
*** 開始 ***
sample01.pdf
(0, 0)
(1190.551, 841.8898)
90
*** 終了 ***
```
log_xxx()/dump()

# はじめに
EC-CUBEというかSymfony3アプリケーションのデバックでデータのダンプなど

# log_xxx()
## log_error()/log_info()など

```php:app/Customize/Controller/SamplePageController.php
/**
 * @Route("/sample/{id}", name="sample_index")
 * @Template("Sample/index.twig")
 */
public function index($id)
{
    $product = $this->productRepository->find($id);
    $size_a = $product->getProductSize()->getSizeA();
    $size_b = $product->getProductSize()->getSizeB();

    log_info(sprintf("%s(%d)", __FILE__, __LINE__), [$size_a, $size_b]); // Arrayだけ

    $product->getProductSize()->setSizeA($size_a + 1);
    $this->entityManager->persist($product);
    $this->entityManager->flush();

    return [
        'shop_name' => $this->baseInfo->getShopName(),
        'product_name' => $product->getName(),
        'maker_name' => $product->getMakerName(),
        'size_a' => $product->getProductSize()->getSizeA(),
    ];
}
```

## Symfony Profiler
SymfonyProfiler→Logs→Info&Errors
![Screenshot_2018-12-27 Symfony Profiler(1).png](https://qiita-image-store.s3.amazonaws.com/0/77040/6fc6b423-8c67-d348-2ab4-32a9d7f315d8.png)



# dump()

```php:app/Customize/Controller/SamplePageController.php
/**
 * @Route("/sample/{id}", name="sample_index")
 * @Template("Sample/index.twig")
 */
public function index($id)
{
    $product = $this->productRepository->find($id);
    $size_a = $product->getProductSize()->getSizeA();
    $size_b = $product->getProductSize()->getSizeB();

    dump($product); // Objectでも良い
    dump([$size_a, $size_b]); // Arrayでも良い

    $product->getProductSize()->setSizeA($size_a + 1);
    $this->entityManager->persist($product);
    $this->entityManager->flush();

    return [
        'shop_name' => $this->baseInfo->getShopName(),
        'product_name' => $product->getName(),
        'maker_name' => $product->getMakerName(),
        'size_a' => $product->getProductSize()->getSizeA(),
    ];
}
```


## Symfony Profiler
SymfonyProfiler→Debug
![Screenshot_2018-12-27 Symfony Profiler(2).png](https://qiita-image-store.s3.amazonaws.com/0/77040/0394d31d-a77a-c59b-bc44-7ac0588c3ef4.png)
soracom-cli をワンライナーで更新する

soracom-cli を使ってて `The latest version v0.4.0 is released which is newer than current version v0.3.9. Please update to the latest version.` と出てきたら更新しましょう。

## ワンライナーで更新する

`~/.local/bin/soracom` に配置するとしてます。

```console
curl -o - -L https://github.com/soracom/soracom-cli/releases/download/v0.10.4/soracom_0.10.4_linux_amd64.tar.gz | tar xzf - -C ~/.local/bin/ --strip=1 --wildcards "*/soracom" --no-same-owner --no-same-permissions
```

* tar のオプションの意味は man なり [tarで特定ファイルだけ取り出したり余分なディレクトリを作らないようにしたりなどのオプションメモ](https://qiita.com/kawaz/items/46217733da8050132ce1) をご覧ください
    * tar のバージョンや実装によっては `--wildcards` が必要になるかもです
* もしかすると最後に `chmod` したほうが良いかも
* バージョン番号は手動で更新してください
    * [GitHub Releases にアップロードしてある最新バージョンの成果物を取得するワンライナー](https://qiita.com/dtan4/items/1a9f16ff881ac456c18f) という方法もあるけれど。ちょっと労力に見合わない気がしている

## あとがき

いろいろ検証してると、TIPS的知見が多くなります。

EoT