OmniAICreator/Qiita-1.07M huggingface dataset:
今年の言語はRust その４９

# 今年の言語はRust その４９

Rustを学びます

Rustの日本語ドキュメント 2nd Edition
https://doc.rust-jp.rs/book/second-edition/

オリジナル(英語)
https://doc.rust-lang.org/book/


## 実行環境

```sh
$ cargo -V
cargo 1.33.0 (f099fe94b 2019-02-12)

$ rustup -V
rustup 1.17.0 (069c88ed6 2019-03-05)

$ rustc --version
rustc 1.33.0 (2aa4c46cf 2019-02-28)

$  cat /proc/version
Linux version 4.14.97-74.72.amzn1.x86_64 (mockbuild@gobi-build-64002) 
(gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)) 
#1 SMP Tue Feb 5 20:59:30 UTC 2019

$ uname -a
Linux ip-10-100-0-8 4.14.97-74.72.amzn1.x86_64 
#1 SMP Tue Feb 5 20:59:30 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/\*release
NAME="Amazon Linux AMI"
VERSION="2018.03"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2018.03"
PRETTY_NAME="Amazon Linux AMI 2018.03"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2018.03:ga"
HOME_URL="http://aws.amazon.com/amazon-linux-ami/"
Amazon Linux AMI release 2018.03

```

## 17. Rustのオブジェクト指向プログラミング機能


### 17.1 オブジェクト指向言語の特徴


#### オブジェクトはデータとふるまいを含む


>オブジェクト指向プログラムは、オブジェクトで構成される。オブジェクトは、 データとそのデータを処理するプロシージャを梱包している。このプロシージャは、 典型的にメソッドまたはオペレーションと呼ばれる。

#### カプセル化は実装詳細を隠ぺいする


オブジェクトの公開APIと、詳細実装を分けて考える。

```rust

pub struct AveragedCollection {
  list: Vec<i32>,
  average: f64,
}

impl AveragedCollection {
  
  pub fn add(&mut self, value: i32){
    self.list.push(value);
    self.update_average();
  }

  pub fn remove(&mut self) -> Option<i32> {
    let result = self.list.pop();

    match result {
      Some(value) => {
        self.update_average();
        Some(value)
      },
      None => None,
    }
  }

  pub fn average(&self) -> f64 {
    self.average
  }

  fn update_average(&mut self) {
    let total: i32 = self.list.iter().sum();
    self.average = total as f64 / self.list.len() as f64;
  }

}
```

### 17.2 トレイトオブジェクトで異なる型の値を許容する

GUIを例にトレイトを実装していきます

GUIの子コンポーネントを管理するScreen構造体と、 Button構造体です。

```rust
pub trait Draw {
  fn draw(&self);
}

pub struct Screen {
  pub components: Vec<Box<Draw>>,
}


impl Screen {

  pub fn run(&self) {
    for component in self.components.iter() {
      component.draw();
    }
  }

}


pub struct Button {
  pub width: u32,
  pub height: u32,
  pub label: String,
}


impl Draw for Button {
  fn draw(&self) {
    // -- skip
  }
}


```

この例では、使用者が、かってに__SelectBox__ を定義して使っています

```rust

use gui::Draw;
use gui::{Screen, Button};

struct SelectBox {
  width: u32,
  height: u32,
  options: Vec<String>,
}

impl Draw for SelectBox {
  fn draw(&self) {
    // -- skip
  }
}


fn main() {

  let screen = Screen {
    components: vec![
      Box::new(SelectBox{
        width:75,
        height:10,
        options:vec![
          String::from("Yes"),
          String::from("Maybe"),
          String::from("No"),
        ],
      }),
      Box::new(Button{
        width:50,
        height:10,
        label: String::from("OK"),
      }),
    ],
  };

  screen.run();

}
```


イエス！
【Ruby】配列内の配列のkeyをで重複をなくす方法

# やりたかったこと
配列内に配列があり、その配列内の1要素をkeyとして重複を消したい。

---

# 環境
```
ruby 2.5.1p57 (2018-03-29 revision 63029)
```

---

# sandbox.rb
```ruby:sandbox.rb
def test()
  array = [["id01",111,"1"],["id01",222,"2"],["id02",111,"1"],["id02",222,"2"],["id01",333,"3"]]
  p array.group_by{ |e| e.first }.select { |k, v| v}.map{|m| m.last.last}
end
test()
```

---

# 内容
<a href="http://starship.hatenablog.com/entry/2017/11/24/180527" target="_blank">Ruby: 配列で重複してるものを探す - 宇宙船サンドボックス</a>を参考に記述を変更した。
業務上1億件近くのデータを扱うため速度は重要だった。
配列で重複した場合は後勝ちとした。

---

# 結果

```ruby:これが
[["id01", 111, "1"], ["id01", 222, "2"], ["id03", 111, "1"], ["id02", 111, "1"], ["id02", 222, "2"], ["id01", 333, "3"]]
```
```ruby:これに
[["id01", 333, "3"], ["id02", 222, "2"], ["id03", 111, "1"]]
```

これで早くなった。
もっといい方法があれば教えてほしい。
コメントいただいてありいがとうございます！

※備忘録に近いが記載する。
Leetcode #95: Unique Binary Search Tree II

```swift
func generateTrees(_ n: Int) -> [TreeNode?] {
    if n == 0 {
        return []
    }
    return helper(1, n)
}

private func helper(_ start: Int, _ end: Int) -> [TreeNode?] {
    if start > end {
        return [nil]
    }
    var treeNodes = [TreeNode?]()
    for i in start...end {
        let leftTrees = helper(start, i-1)
        let rightTrees = helper(i+1, end)
        for leftIndex in 0..<leftTrees.count {
            for rightIndex in 0..<rightTrees.count {
                let head = TreeNode(i)
                treeNodes.append(head)
                head.left = leftTrees[leftIndex]
                head.right = rightTrees[rightIndex]
            }
        }
    }
    return treeNodes
}
```
Arch Linux を触り始めた感想を簡単にまとめる

## はじめに

趣味がてら、Arch Linux を数日あれこれ触ってみていました。

初めて触る Linux だったこともあり、ハマることも多かったのですが、その過程が楽しいなと感じました。

この記事では、Arch Linux を触り始めて感じたことをまとめてみようと思います。

## 経緯

普段仕事で使っているのは Mac なのですが、少し気分を変えてみたいなと思い、Linux 環境を立ち上げてみようと思い立ちました。

Ubuntu や CentOS は多少触ってきたことはあったので、それをもう一回触るのもなんだかなと思っていました。

そこで、どうせならあまり触ったことがない Linux をいじってみようということで探していたところ、Arch Linux が良さそうだったので、VirtualBox 上で触ってみることにしました。

### Arch Linux を選んだ理由

Arch Linux の設計哲学が魅力的だったのが大きいです。

以下、[Arch Linux - ArchWiki](https://wiki.archlinux.jp/index.php/Arch_Linux) から抜粋します。

> Arch Linux は、軽量、柔軟、シンプル、および UNIX ライクであることを目指しています。インストールでは x86-64 用にコンパイルされた最小限 (非GUI) の環境が提供され、不必要なパッケージは含まれません。ユーザーは不要な、あるいは迷惑なパッケージを削っていくのではなく、あらかじめ選択されたデフォルトなどのない最小構成からシステムを作り上げることができます。Arch の設計哲学および実装は、最小構成のコンソールマシンから壮大で機能豊富なデスクトップ環境まで、要求されたいかなる種類のシステムへの拡張をも容易にします。どんな Arch システムにするかはユーザーが決めるのです。

上記の様に、最小構成から必要なもののみインストールしていくということで、不要なものは切り捨てて軽い状態にできるというところに惹かれました。

というのも、Mac を触っている中で、どうしても動作が重くなってしまうシーンがあったので、最小構成で環境を組んだらどんな体験ができるのだろう？という技術的興味が湧きました。

また最近 [UNIXという考え方―その設計思想と哲学](https://amzn.to/2Ln7ldV)という本を読んでいて、UNIX 哲学にも興味が湧いていたので、UNIX ライクと謳っている Arch Linux を触ることを通じて、UNIX 哲学を学ぶこともできそうだというところも魅力的でした。

## Arch Linux を触り始めて感じたこと

ここからは Arch Linux を触り始めて感じたことをつらつら書いていこうと思います。

### Linux に関する理解を深められる

最近の Linux はインストールが非常に簡単にできるようになってきていると思います。しかし Arch Linux の場合は、ディスクのパーティションを切るところから自分でコマンドを実行しながらインストールを進めなければなりません。

以下のインストールガイドを見ると、パーティションを切って、ファイルシステムを準備して、ネットワークを疎通して、というように、すべて手動でインストール作業を進める形となっています。

[インストールガイド - ArchWiki](https://wiki.archlinux.jp/index.php/%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%82%AC%E3%82%A4%E3%83%89)

一見面倒ではあるのですが、Linux に関する理解を深めるということを目的に置くと、自分でインストール作業を実施することはとても勉強になるなと感じました。

### 自分好みに環境をカスタマイズするモチベーションが湧く

Arch Linux を最小構成でインストールしたあとは、CUI しかなく、デスクトップ環境すらありません。

最初はとても普段使いできる状態ではなく不便なのですが、そこから試行錯誤しながら徐々に自分好みの環境にカスタマイズしていくという過程が楽しいなと感じました。

例えば Mac で何気なく使っていたダークモードっぽいデスクトップにしようと思ったとき、Arch Linux にはそもそもデスクトップ環境自体がないため、

* デスクトップ環境を何を使って立ち上げる？GNOME？KDE？Xfce？
* デスクトップのテーマ何にする？
* デスクトップの壁紙何にする？
* ...

というふうに、ゼロから自分の理想の形を必然的に考えていくことになります。

仕事中だとフラストレーションが溜まる状況になりがちですが、自由な時間に自由な発想で考えていくのは楽しいなと感じました。

また [UNIXという考え方―その設計思想と哲学](https://amzn.to/2Ln7ldV)には、「好みに応じて自分で環境を調整できるようにする」という一節がありますが、Linux はすべての設定を制限なくカスタマイズできる自由が存在します。

「この設定、どう変更するのだろう？」ということをあれこれ調べていくのも楽しいなと思いました。

## おわりに

もし Arch Linux を触り始めようと思っている方は、まず[インストールガイド - ArchWiki](https://wiki.archlinux.jp/index.php/%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%82%AC%E3%82%A4%E3%83%89)を読むことから始まると思います。

僕もまだ入門したてで、まだ触り始めて間もないですが、いずれ仕事でも使えるような環境に育てていけるよう、試行錯誤を続けていこうと思います。
unknown型とタイプガードと私

自戒と備忘録として。typescript 3.4.5 で以下は確認しています。

typescript 3系で unknown 型が導入され、オッ外部からのデータを受け付ける箇所から any が撲滅できるのではないか、みたいなことを思ったことがあるわけです。

ただ、

```typescript
type User = {
  name: string;
  age: number;
};

const data: unknown =
   JSON.parse(`{ "user": { "name": "user", "age": 18 } }`);
```

こういう unknown なデータがあった時に、なんとなく以下のように書けそうに思うけどうまくいかない。

```typescript
if(data && typeof data === 'object'){
  if("user" in data){
    const user = data.user; // Error, data["user"] でもいっしょ
    if (
      user &&
      typeof user === "object" &&
      typeof user.name === "string" &&
      typeof user.age === "number"
    ) {
      doSomethingFor(user)
    }
  }
}
```

`プロパティ 'user' は型 'object' に存在しません。ts(2339)` とそっけなく言われてしまう。それはそうかもしれないけど、`if("user" in data)` してるんだからそこは推論してほしい気持ちはある。一度 any とか `{}` にキャストしてしまうのも一つの方法だが、率直に意図が読みづらいコードになるのは間違いない。

ここはタイプガード関数を通すとよいみたい。

```typescript
const hasUser = (d: any): d is { user: User } => {
  if (!d) return false;
  if (d.user && typeof d.user === "object") {
    if (
      typeof d.user.name === "string" &&
      typeof d.user.age === "number"
    ) {
      return true;
    }
  }
  return false;
};

// 以下は通る。
if (hasUser(data)) {
  const user: User = data.user;
}
```

あれ、 any が出現しているぞ・・・?　でもこの `hasUser` が公開する受け入れ可能な引数の型が any なのは自然なのだ。unknown しか受け付けない関数とか、（外から見たら）意味がわからない。

というわけで、

1. unknown は any を返す関数の戻り値を受け取るときに使う
2. unknown で受けたあとは明示的に型チェックを行うタイプガードを通す
3. プリミティブでないことが期待されるデータを unknown で受けたら、どこかで any が混入することにはそういうものです

というところに落ち着いたがまだ釈然としていない。

個人的には `if("user" in data && typeof data.user)` は許してほしかったところだけど。でも、 `unknown` の問題というより typescript の `object` 型の扱いに問題があるような気がしてきた。

[関連 Issue](https://github.com/Microsoft/TypeScript/issues/25720) については引き続き眺めていきたいところ。
Arduinoを用いてソレノイドを動かす

# 目的
Arduinoを用いてソレノイドを動かした際の記録です。
ソレノイドは弁の開閉制御などに使われる電子部品の一つです。

> https://ja.wikipedia.org/wiki/ソレノイド

# 準備
[Arduino UNO](https://www.amazon.co.jp/gp/product/B01N0KMFGF/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1)
[uxcell ソレノイドバルブ 電磁石弁 小型 メタル 電子部品 DC 12V 300mA 引きタイプ 直線運動 JF-0730B](https://www.amazon.co.jp/gp/product/B00GWFABCE/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)
[トランジスタ　2sc1815](https://www.amazon.co.jp/gp/product/B00RGDMZMK/ref=ppx_yo_dt_b_asin_title_o08_s00?ie=UTF8&psc=1)
[シリコンダイオード　（100V　1A）](https://www.amazon.co.jp/gp/product/B00J5983YC/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)
12V電源

# 回路図

![sole.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344880/cffc2566-114c-b507-39a8-afc88e586ef8.png)


下記のようになります。
<img width="160" alt="スクリーンショット 2019-04-29 20.51.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344880/4b1db8fa-04be-7511-c724-46f0e81cbb08.png">

# コード

PIN8のON/OFFを繰り返します。

```:sample
void setup() {
  pinMode(8, OUTPUT);
}

void loop() {
  digitalWrite(8, HIGH);
  delay(100);
  digitalWrite(8, LOW);
  delay(400);
}
```

# テスト

電源ONにした後、ソレノイドが一定の間隔で動作すればOK
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">solenoid on/off <a href="https://t.co/xh3cG38YLD">pic.twitter.com/xh3cG38YLD</a></p>&mdash; st (@st17890027) <a href="https://twitter.com/st17890027/status/1122787928290119680?ref_src=twsrc%5Etfw">April 29, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 


# 参考
[ソレノイドをArduinoで制御しよう!【Part1】](https://ameblo.jp/solcon/entry-12278991497.html)
[試行錯誤な日々](http://asukiaaa.blogspot.com/2016/01/arduino12v.html)
[ニケルの工作日記](http://nickelab.blog.fc2.com/blog-entry-68.html)
[共立エレショップ 小型プッシュソレノイド DC12V PS-12B](http://eleshop.jp/shop/g/gECC412/)
[東芝トランジスタ-2SC1815](http://www.op316.com/tubes/tips/image/2sc1815.pdf)
SQLiteのインメモリモードとファイルモードの性能を比較してみた

- 簡単なベンチマークプログラムを用いてインメモリモードとファイルモードのCRUDの性能を比較

# 概要

ふと「SQLiteってインメモリモードとファイルモードでどれくらい性能差があるのか？」という疑問が浮かんだので、なるべく時間をかけずにベンチマークコードを書いて試してみた。せっかくなので結果を共有する。

# 結果

単位は秒。10回実施した平均値を示す。

## Mac/SSD

```
  機種ID:	MacBookPro10,2
  プロセッサ名:	Intel Core i5
  プロセッサ速度:	2.5 GHz
  メモリ:	8 GB
```

|#|操作|ファイルモード|インメモリモード|
|---|---|--:|--:|
|1|100万行のbulk-insert|6.290|5.835|
|2|1行をinsert|0.247|0.225|
|3|文字列カラムでソート|0.221|0.195|
|4|数値カラムでソート|0.238|0.175|
|5|文字列・数値でフィルタ|0.008|0.007|
|6|更新|0.130|0.086|
|7|削除|0.186|0.127|

## Windows/HDD

```
プロセッサ: Intel Core i7-7700
プロセッサ速度: 3.6 GHz
メモリ: 32 GB
```

|#|操作|ファイルモード|インメモリモード|
|---|---|--:|--:|
|1|100万行のbulk-insert|4.655|3.417|
|2|1行をinsert|0.285|0.132|
|3|文字列カラムでソート|0.209|0.185|
|4|数値カラムでソート|0.242|0.220|
|5|文字列・数値でフィルタ|0.009|0.007|
|6|更新|0.556|0.105|
|7|削除|0.781|0.127|

# ベンチマークコード

Githubで公開している。

- SQLite Benchmark
    - https://github.com/ytkj/sqlite-benchmark

以下は抜粋。

```python
db.create_all()
sw = StopWatch()
sw.start()

entities = [dict(
    text1=random_text(3),
    text2=random_text(3),
    number1=random(),
    number2=random(),
) for i in range(args.records)]
sw.wrap('generate {0} records'.format(args.records))

db.session.execute(ItemMapper.__table__.insert(), entities)
db.session.commit()
sw.wrap('bulk insert {0} records'.format(args.records))

del entities

item = ItemMapper()
item.text1 = 'aaa'
item.text2 = 'bbb'
item.number1 = 0.1
item.number2 = 0.2
db.session.add(item)
db.session.commit()
sw.wrap('insert 1 records')

result1 = ItemMapper.query.order_by(ItemMapper.text1, ItemMapper.text2).offset(1000).limit(20).all()
sw.wrap('select order by text1, text2 offset 1000 limit 20')

result2 = ItemMapper.query.order_by(ItemMapper.number1, ItemMapper.number2).offset(1000).limit(20).all()
sw.wrap('select order by number1, number2 offset 1000 limit 20')

result3 = ItemMapper.query.filter(ItemMapper.text1.startswith('a')) \
    .filter(ItemMapper.number1 > 0.5).offset(1000).limit(20).all()
sw.wrap('select where text1 like a* and number1 > 0.5 offset 1000 limit 20')

ItemMapper.query.filter(ItemMapper.text1 == 'aaa').update(dict(text1='bbb'))
db.session.commit()
sw.wrap('update text1 bbb where text1==aaa')

ItemMapper.query.filter(ItemMapper.text1 == 'bbb').delete()
db.session.commit()
sw.wrap('delete where text1 == bbb')

sw.describe()
reports.append(sw.get_report())

db.drop_all()
```
Django入門編を終えた感想

##はじめに
以下のページを参考に、PaizaCloud上で簡単なWebアプリケーションを作成してみました。
https://paiza.hatenablog.com/entry/2018/02/28/paizacloud_django

今回は実際にDjangoを利用してみて驚いた点を紹介します。

##モデルファイルを元にテーブルが作成される
Djangoでアプリケーションディレクトリ上で作成した「models.py」の定義データを元にテーブルが作成されます。
要するに**アプリケーションで使用するテーブルを作成するためのDDL実行などが一切不要ということです。**
手順は以下のようになります。

【1】modelファイル作成(models.py)

```
from django.db import models

# テーブル名は「アプリケーション名 + "_" + メソッド名」の形式で作成されます
# 1メソッド：1テーブル
class Post(models.Model):
    # カラム名 = models.作成するカラムの種類に該当するメソッド(定義情報) 
    body = models.CharField(max_length=200)
```

【2】マイグレーションファイル作成
models.py を元に、以下コマンドによりマイグレーションファイル(※1)を作成する。
(※1)テーブルを作成するための定義ファイル。「models.py」を元に作成される。

```
$ python manage.py makemigrations アプリケーション名
```
★実際には上記コマンドを実行したことによりアプリケーションディレクトリに「migrations」というディレクトリが作成されました。「migrations」の中にはテーブルの定義情報、スクリプトが格納されているようです。

【3】DB反映
以下コマンドを実行し、【2】で作成したマイグレーションファイルの情報をDBへ反映する。
(【2】で一緒に作成された「migrations」ディレクトリ内のスクリプトが実行される模様)

```
$ python manage.py migrate
```

【4】テーブル定義情報を確認する
【1】でmodels.pyに定義したテーブル情報が実際にDBに定義されていることを確認する。

```
# インストールしているDBシェルを呼び出し(入門編ではmysqlを使用)
$ python manage.py dbshell

# 定義されているテーブル一覧参照
# todo_postテーブルが作成されていることを確認(アプリケーション名は「todo」)
mysql> show tables;
+----------------------------+
| Tables_in_mydb             |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| todo_post                  |
+----------------------------+
11 rows in set (0.00 sec)

# todo_postテーブルのカラム情報を参照
# bodyカラムが定義されていること
# ※なお、PrimaryKeyが定義されていない場合は自動でidカラムがPrimaryKeyとして定義される模様
mysql> describe todo_post;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| body  | varchar(200) | NO   |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

```

上記の仕様により、models.pyファイルの共有のみで各環境ごとに同じテーブル定義を容易に利用できるようです。テーブル定義情報を別途持ちまわる必要がないため、非常に開発効率が良いように思えます。
## FW標準のDB管理画面が用意されている
管理者ユーザを作成(コマンド：python3 manage.py createsuperuser)し、「admin.py」ファイルを作成することにより、ブラウザ経由でDB管理画面を表示することができる。

以下が管理画面へのログイン画面。
(標準でログイン画面まで利用できる。すごい・・)
![管理画面-ログイン.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407364/efe9be73-95c5-e36b-ed8a-db965583df53.png)

これが実際の管理画面です。(現在bodyカラムが「テスト」というレコードが登録されてます。)
データの追加/削除等が可能な模様。
![管理画面-実際.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407364/0358f59d-9d55-1c17-b59c-b6fe8e4b1a8f.png)

管理画面に関してはカスタマイズが可能なようです。
詳細は今後勉強していきます。

##Next
入門編を終えたため、今後は簡単なWebアプリケーションを作成する予定です。
Djangoの他標準機能を試運転できるような開発ができればと考えてます。
(案探し中。。)
GitHub に公開されている Defold 製のサンプルゲーム

[Defold 1.2.151](https://www.defold.com/release-notes/1.2.151/) (APR 15, 2019 リリース版)でビルドできることを確認しました。

# Defold 公式チュートリアル

* [Getting started with Defold](https://www.defold.com/tutorials/getting-started/) - チュートリアル
* [GitHub \- defold/defold\-examples: Defold Examples](https://github.com/defold/defold-examples/) - サンプルゲーム

# サンプルゲーム集

* [GitHub \- britzl/publicexamples: Examples for the Defold engine](https://github.com/britzl/publicexamples)
  * Play: [Defold Public Examples](http://britzl.github.io/publicexamples/) 
* [GitHub \- benjames\-171/defold\-games: Collection of simple games made with Defold](https://github.com/benjames-171/defold-games)
* [AJirenius \(SetTheBet\) / Repositories · GitHub](https://github.com/AJirenius?tab=repositories)

# Pong

* [GitHub \- britzl/pong: Defold implementation of the classic game Pong](https://github.com/britzl/pong)
 * Play: [Pong](https://britzl.github.io/Pong/)

# ブロック崩し (Breakout)

* [GitHub \- AJirenius/BreakoutClone](https://github.com/AJirenius/BreakoutClone)
* [GitHub \- britzl/breakout: Breakout clone for the Defold game engine](https://github.com/britzl/breakout)
 * Play: [Breakout](http://britzl.github.io/publicexamples/breakout/index.html)

# インベーダー

* [GitHub \- britzl/lowrezinvaders: Lowrez Space Invanders clone for the Defold game engine](https://github.com/britzl/lowrezinvaders)
 * Play: [Lowrez Invaders](https://britzl.github.io/lowrezinvaders/) 

# テトリス

* [GitHub \- joachimvalente/defold\-tetris: Tetris made with Defold](https://github.com/joachimvalente/defold-tetris)

# パックマン

* [GitHub \- AJirenius/PacmanClone](https://github.com/AJirenius/PacmanClone)

# Flappy Bird

* [GitHub \- d954mas/defold\-flappy\-bird: flappy bird game made in defold](https://github.com/d954mas/defold-flappy-bird)
 * Play: [Flappy Zombie](https://d954mas.github.io/defold-flappy-bird/)
* [GitHub \- AJirenius/FlappyClone](https://github.com/AJirenius/FlappyClone)

# Angry Birds

* [GitHub \- britzl/throwacrow at improved](https://github.com/britzl/throwacrow/tree/improved)
 * Play: [Throw a Crow](http://britzl.github.io/publicexamples/throwacrow/index.html)
PHPアカウント登録機能メモ

PHPを学び始めたので、分かったことをメモしていく。

strlen()を知った時に
"〇文字以上〇文字以下でアカウント名(パスワード)を登録する"
という機能を作れるのではないかと思いコードを書いてみた。

```php
$name = 123456789;   //使用可能です。

if (strlen($name)<=12 && strlen($name)>=4)
{
  echo "使用可能です";
}
elseif (strlen($name)<4) {
  echo "4文字以上で名前を設定してください。";
}
else
{
  echo "12文字以下で名前を設定してください。";
} 
```

Qiita初投稿なので、これからもっとアウトプットしていきたい。
綺麗にコードをかけるようになりたい。
プログラミング学習記録76〜おみくじゲーム〜

##今日やったこと
- ドットインストール「JavaScriptでおみくじを作ろう」でおみくじを作り、少しアレンジする
- アレンジしたものをYouTubeに投稿する
- ドットインストール「JavaScriptでタイピングゲームを作ろう」を途中までやる

前回と同じようにドットインストールで作ったものを少しアレンジして、動作している様子をYouTubeに投稿してみました。
[ドットインストール「JavaScriptでおみくじを作ろう」を少しアレンジして作ったもの](https://youtu.be/6yUr-IsetWs)

おみくじの種類を増やして、確率を調整しました。
<br>
<br>
また、以下のようにjsとCSSを記述して、ボタンを作りました。

mousedownはマウスボタンが押された時、mouseupはマウスボタンを離した時に起こるイベントです。

以下のように書くと、押された時にbtnにpressedというクラスが追加されて、離した時にはpressedクラスが外されます。

```javascript
btn.addEventListener('mousedown' , () => {
    btn.classList.add('pressed');
  });


btn.addEventListener('mouseup' , () => {
    btn.classList.remove('pressed');
  });
```
```css
#btn.pressed{
  box-shadow: 0 5px 0 #d1483e;
  margin-top: 35px;
}
```

<br>

＃05のMath.random() Math.floor()の解説がめちゃくちゃわかりやすかったです。

「はじめてのJavaScript」の途中に#05を差し込んで欲しい、と思いました。

明日も頑張ります。
<br>
おわり
metaタグを用いたリダイレクト機能で躓いた件

＃概要
HTMLにおける\<meta\>タグを使用した
リダイレクト機能をテストした際に
指定URLに飛ばずに四苦八苦し記録です。

#背景
基礎からのMySQLを進める途中、
まさにその基礎勉強に飽き飽きし、
PHPの学習に飛んだ時の話です。

phpの話に入ったばかりの課題が
表題の件でした。
（最初にやることじゃなくね…？）

#開発環境
MacOS Mojave
PHP 7.1.23
Apache 2.4.39
使用ブラウザ Safari

#内容

初期に書いたコードは以下の通りでした。
文法は「基礎からのMySQL」に基づいていますが、
ちょっとだけアレンジしています。

```php:test.php
<?php
print "<head>";
print " <meta http-equiv='refresh' content=5; URL='http://www.softbank.jp/'>";
print "</head>";
print "<body>";
print "5秒後にソフトバンクのページへ移動します";
print "</body>";
?>
```

何とも言えないクソコードですね。
出力結果を見てみましょう。

```
5秒後にソフトバンクのページへ移動します
```

↓5秒後…

```
5秒後にソフトバンクのページへ移動します
```

ページは変わらず、永遠と5秒ずつ同じページを
更新し続けています。
書籍の説明では、5秒後に
指定したURL先にジャンプするはずなのですが…

#対処
ググりにググり、リダイレクト機能について調査
しましたが、ほとんどのサイトが上記の記述で
説明されていました。

ところが、ある一つのサイトだけ
違った記述方法でした。

その記述方法を用いて訂正したコードを
下記に示します。

```php:test.php
<?php
print "<head>";
//シングルクオートの位置が違う
print " <meta http-equiv='refresh' content='5; URL=http://www.softbank.jp/'>";
print "</head>";
print "<body>";
print "5秒後にソフトバンクのページへ移動します";
print "</body>";
?>
```

訂正前はURLのみをシングルクオートで囲っていましたが

```php:訂正前
<meta http-equiv='refresh' content=5; URL='http://www.softbank.jp/'>
```

訂正後はcontentで指定する秒数の前からシングルクオートで
囲っています。

```php:訂正後
<meta http-equiv='refresh' content='5; URL=http://www.softbank.jp/'>
```

結果、出力は以下の通りになりました。

```
5秒後にソフトバンクのページへ移動します
```

↓5秒後…

```
（ソフトバンクホームページ）
```

成功しましたね。

#結局何が原因なの？
現時点で分かっていません。
教えてエロい人。

#参考書籍
基礎からのMySQL
[参考サイト](https://web-laboratories.com/meta-refresh)
Flaskでクエリストリングを獲得する際に、思った値が取れない原因と対策

# はじめに
Flaskを使っているときにGETやPOSTで想定通りのパラメータを取得することができず１時間くらい右往左往したため、忘記録として記述しておく。

# 問題が起きたプログラム
問題となったのは、パラメータlで受け取ったURLにリダイレクトするだけの以下のAPI。
なお粗末なプログラムですが、[GitHub](https://github.com/kazuaki-i/redirector)で公開しているので興味のある方はどうぞ。


```python
import string
from flask import Flask, request


HTML = '''\
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>redirect</title>
<meta http-equiv="refresh" content="0; URL='${link}'" />
</head>
<body>
    このページは自動的に転送されます。<br>
    転送されない場合は<a href="${link}">こちら</a>をクリックしてください
</body>
</html>
'''

app = Flask(__name__)


@app.route('/')
def index():
    link = request.args.get('l', '')
    assert link, 'Cannot get l parameter querystring'
    return string.Template(HTML).substitute({'link': link})
```

上記のWebアプリを`html://hoge.com/r/`に配置して、パラメータlに適当なURLを与えてやる。たとえば、次のような感じで使うことを想定している。

```
http://hoge.com/r/?l=http:fuga.com/
```

## 問題と原因
パラメータlに色々なURLを放り込んでみるが、クエリを持つURLを与えると思った通りのリダイレクトをしてくれない。たとえば、以下のような感じ。

```
html://hoge.com/r/?l=http:fuga.com/?q=1&date=20190501
```

問題は明らかで、与えたl内に?や&が入っていること。解決するにはなんとかこれを消してやればよい。
replaceなどの力技も可能だが、極力スマートにやりたい。~~（あとAPI側をいじりたくない~~

## 解決策
リダイレクト先のURLを作ったあとに`urllib.parse.quote`をかけてやることで解決する。

```python
import urllib

target = 'http:fuga.com/?q=1&date=20190501'
return 'html://hoge.com/r/?l=' + urllib.parse.quote(target)
```

これでlで指定したURL(パラメータ付き)に正しくアクセスできる。
あとAPI側での修正は必要ない。よしなにデコードしてくれるようだ。

## おまけ
実はこの`urllib.parse.quote`は非常に便利で、たとえば、クロールしてきたWebページを保存するときに、そのURLをエンコードしてやることでファイル名として扱えたりできる。
プログラミング学習記録75〜ちょいアレンジして動画投稿〜

##今日やったこと
- Progate JavaScript1そのまま復習
- ドットインストール「はじめてのJavaScript」で作った簡単なゲームをちょっとアレンジしてYouTubeに投稿
- ドットインストール「JavaScriptでおみくじを作ろう」を視聴

Progateはそのまま復習だけしました。
実際にコードを書いて復習しなくてもよさそうです。
<br>

ドットインストールの「はじめてのJavaScript」で作ったミニゲームをちょっとだけアレンジしたものをYouTubeに投稿してみました↓

[ドットインストール「はじめてのJavaScript」を少しアレンジして作ったもの](https://youtu.be/_3d5v5GHn80)

ただ動画を見て受動的に作るよりも「どこか変えられるところはないか？」と考えながらコードを書いた方が身になると思います。

なので、当たりの時の背景色と回転数だけですが、変えてみました。

こんな感じで作ったものを動画でアップロードしてみるのもモチベーションになっていい気がします。
<br>
あと、「JavaScriptでおみくじを作ろう」の動画を見ました。

今までは１動画見る→コード書く→１動画見る→コードを書く→…という感じだったのですが、今日は1回最後まで動画を見てみることにしました。

1回最後まで見てみた結果、全体像がわかってからコードを書いた方が理解しやすいのではないかと思いました。

続きはまた明日やってみます。

おわり
JavaScriptでボタンを螺旋状に配置する

ソース

```html:test.html
<div id="div1"></div>

<script>
    var x = 0
    var y = 0
    var vec = 0//↑→↓←の順で0~3
    var co = 0
    var max = 1

    var num = 100//ボタンの数
    var margin = 40//ボタン間の距離
    var div1 = document.getElementById("div1")

    function next() {
        if (co == max) {
            co = 0
            if (vec == 1 || vec == 3) { max++ }
            vec++;
            if (vec > 3) { vec = 0 }
        }
        co++

        if (vec == 0) {
            y++
        } else if (vec == 1) {
            x++
        } else if (vec == 2) {
            y--
        } else if (vec == 3) {
            x--
        }
    }

    for (var i = 0; i < num; i++) {
        var b = document.createElement("button")
        b.innerText = "" + i
        b.style.position = "absolute"
        b.style.left = window.innerWidth / 2 + x * margin + "px"
        b.style.top = window.innerHeight / 2 + y * margin + "px"
        b.style.backgroundColor="rgb("+(250-i)+",250,100)"
        div1.appendChild(b)

        next()
    }
</script>
```

結果
![aaキャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398685/71e66f52-79a5-2f0d-4b3d-018fc20a307d.png)

何に使えるかはわかりません
Ethereum Walletアプリ 作り方

#概要
react-nativeはパッケージをインストールする手順が間違うだけでエラーが出るのでメモ
またweb3もreact-nativeの特定のバージョンだけしか動かない
#各種パッケージインストール
react-nativeの導入は[こちら](https://qiita.com/tktktktk/items/d407201e4263cf96157b)

まず```package.json```の```dependencies```に以下をコピーして```npm install```


```
{
  "name": "ethereumjs",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "ethereumjs-tx": "^1.3.7",
    "ethereumjs-wallet-react-native": "^0.6.7",
    "node-libs-react-native": "^1.0.3",
    "react": "16.6.3",
    "react-native": "0.57.8",
    "react-native-bip39": "^2.3.0",
    "react-native-randombytes": "^3.5.2",
    "react-native-web3-webview": "^1.2.9",
    "vm-browserify": "^1.1.0",
    "web3": "1.0.0-beta.37"
  },
  "devDependencies": {
    "babel-jest": "24.1.0",
    "jest": "24.1.0",
    "metro-react-native-babel-preset": "0.53.0",
    "react-test-renderer": "16.6.3"
  },
  "jest": {
    "preset": "react-native"
  }
}
```

```
react-native link react-native-randombytes
react-native link react-native-web3-webview
```
ホームディレクトリ以下にglobal.jsを作成

```:global.js
import url from "url";
global.URL = class URL {
  constructor(inputUrl) {
    return url.parse(inputUrl);
  }
};

if (typeof btoa === 'undefined') {
  global.btoa = function (str) {
    return new Buffer(str, 'binary').toString('base64');
  };
}

if (typeof atob === 'undefined') {
  global.atob = function (b64Encoded) {
    return new Buffer(b64Encoded, 'base64').toString('binary');
  };
}
```

あとはこの順番通りにインストール

ローカルDBのrealm

```
npm i --save realm 
react-native link realm
```

ui componentのreact-native-elements

```
npm i --save react-native-elements
```

画面遷移のreact-navigation

```
npm i --save react-navigation
```

あとは頑張って作る
Leetcode #96: Unique Binary Search Trees


```swift
func numTrees(_ n: Int) -> Int {
    var dp = Array(repeating: 1, count: n+1)
    for i in 1...n {
        var tmp = 0
        for j in 0...i-1 {
            tmp += dp[j] * dp[i-j-1]
        }
        dp[i] = tmp
    }
    return dp[n]
}
```
CentOS7  の Nginx で Let's Encrypt を使う

CentOS 7.6 に Nginx をインストールして Let's Encrypt の設定をします。
abc.example.com に設定するとします。

1) http(80),https(443) のポートにアクセスできるようにします。

```bash
sudo firewall-cmd --permanent --add-service=http --zone=public
sudo firewall-cmd --permanent --add-service=https --zone=public
sudo firewall-cmd --reload
```

2) Nginx をインストールします。

```bash
sudo yum -y install nginx
```

設定ファイルは、
/etc/nginx/nginx.conf です。

> root /usr/share/nginx/html;
>を 
> root         /var/www/html;
> に変更しています。

3) Nginx の起動

```bash
sudo systemctl start nginx
sudo systemctl enable nginx
```

ブラウザーで、http://abc.example.com にアクセスします。

4) certbot のインストール

```bash
sudo yum -y install certbot
```

5) 証明書の生成

```bash
sudo certbot certonly --webroot -w /var/www/html -d abc.example.com --email aaa@example.com
```

6) /etc/nginx/nginx.conf の編集

```text:/etc/nginx/nginx.conf
server {
listen  443 ssl;
server_name     abc.example.com;
ssl_certificate         /etc/letsencrypt/live/abc.example.com/fullchain.pem;
ssl_certificate_key     /etc/letsencrypt/live/abc.example.com/privkey.pem;
}
```

7) Nginx の再起動

```bash
sudo systemctl restart nginx
```

https://abc.example.com にブラウザーでアクセス

AWS などだと、OS　の外でポートのアクセスに制限がかけることができるので、外部から 443 ポートにアクセスできるか確認します。

>```bash
nmap -sT abc.example.com
```

次のように表示されれば、アクセスが出来ます。

>```text
PORT     STATE  SERVICE
80/tcp   open   http
443/tcp  open   https
```
VueでKonva.jsとcanvasを使ってお絵描き（その5）

[その4はこちら](https://qiita.com/Butterthon/items/64d5aadf1a0d0bb8aa1f)
  
# 直線を引けるようにする
モードで直線を選択したら直線を引けるようにしようと思います。

・描画開始（マウスダウン）時にその時の座標を取得
・描画中（マウスムーブ）は何もしない
・描画終了（マウスアップ）時にその時の座標を取得

...開始・終了の座標を結んだら直線引けるんじゃね？って思ってやってみたらできました。
  
親(CallCanvas.vue)のほうはすでに直線モードを子に渡せる状態になっているので変更はありません。
  
子(FreeDrawing.vue)を修正します。
以下のようなコメント行の間にあるソースが直線を引くために追加したソースコードです。

```
/** 追加 */
...
..
.
/** 追加ここまで */
```

```FreeDrawing.vue
...
..
.

<script>
import Konva from 'konva'

export default {
  ...
  ..
  .
  methods: {
    mousedown: function () {
      this.isPaint = true

      // マウスダウン時の座標を取得しておく
      this.lastPointerPosition = this.stage.getPointerPosition()

      // 戻す配列に描画前のキャンバスの状態を保存
      this.undoDataStack.push(this.context.getImageData(0, 0, this.canvas.width, this.canvas.height))

      /** 追加 */
      // 直線モード時はマウスダウン時に描画開始座標を指定する
      if (this.isTargetMode('line')) {
        this.context.beginPath()

        this.localPos.x = this.lastPointerPosition.x - this.drawingScope.x()
        this.localPos.y = this.lastPointerPosition.y - this.drawingScope.y()

        // 描画開始座標を指定する
        this.context.moveTo(this.localPos.x, this.localPos.y)
      }
      /** 追加ここまで */
    },
    mouseup: function () {
      this.isPaint = false

      /** 追加 */
      // 直線モード時はマウスアップ時に描画する
      if (this.isTargetMode('line')) {
        this.pos = this.stage.getPointerPosition()
        this.localPos.x = this.pos.x - this.drawingScope.x()
        this.localPos.y = this.pos.y - this.drawingScope.y()

        // 描画開始座標から、lineToに指定された座標まで描画する
        this.context.lineTo(this.localPos.x, this.localPos.y)
        this.context.closePath()
        this.context.stroke()
        this.drawingLayer.draw()

        this.lastPointerPosition = this.pos
      }
      /** 追加ここまで */
    },
    mousemove: function () {
      if (!this.isPaint) {
        return
      }
      // ペンモード時
      if (this.isTargetMode('brush') || this.isTargetMode('line')) {
        this.context.globalCompositeOperation = 'source-over'
      }
      // 消しゴムモード時
      if (this.isTargetMode('eraser')) {
        this.context.globalCompositeOperation = 'destination-out'
      }

      /** 追加 */
      // 直線モード時は何もしない
      if (this.isTargetMode('line')) {
        return
      }
      /** 追加ここまで */

      ...
      ..
      .
    },
    ...
    ..
    .
}
</script>
```
  
引けました！ただ斜め線引いた時に少しギザギザなってしまうところが難点。
（考えを安直にソースにしただけなので仕方ないかもしれないですが。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357470/39b27ef0-1671-6d5d-8da2-e8baafb21d5e.png)

# 備考
直線を引くときにガイドラインを表示してあげたりとかできるとさらに良くなりますね。
気が向いたらやってみます。
Firebase FunctionsでGraphQLを使う

かなり遠回りをして苦労したので記しておきます。とりあえず動くところまで。

## functions書く

firebaseの諸々と、`apollo-server-cloud-functions`を`yarn add`しておきます。したら`/functions/index.js`を下記のようにします。

```javascript:index.js
const functions = require('firebase-functions');
const { ApolloServer, gql } = require('apollo-server-cloud-functions');

const examples = [
  { id: 1, name: 'exam1', message: 'message1' },
  { id: 2, name: 'exam2', message: 'message2' },
  { id: 3, name: 'exam3', message: 'message3' },
]

const samples = [
  { id: 1, title: 'sample1', status: 'ok' },
  { id: 2, title: 'sample2', status: 'ok' },
  { id: 3, title: 'sample3', status: 'bad' },
]

const typeDefs = gql`
  type Query {
    examples: [Example]
    samples: [Sample]
  }

  type Example {
    id: ID!
    name: String!
    message: String!
  }
  
  type Sample {
    id: ID!
    title: String!
    status: String!
  }
  `;

const resolvers = {
  Query: {
    examples: () => examples,
    samples: () => samples,
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

exports.graphql = functions.https.onRequest(server.createHandler());
```

完成。あとは煮るなり焼くなり好きにしてください。

## 動作確認編

`$ firebase serve`してローカルで起こすと`✔  functions: graphql: <url>`というログが吐かれます。そしたらcurlでPOSTしてみましょう。

```
curl -X POST -H "Content-Type: application/json" --data '{"query": "query { samples {id, title}}"}' <url>
```

返ってきたら嬉しいもの

```
{"data":{"samples":[{"id":"1","title":"sample1"},{"id":"2","title":"sample2"},{"id":"3","title":"sample3"},{"id":"4","title":"sample4"}]}}
```

もし返ってこなかったら何かがアレなのでどうにかしましょう。
Leetcode #94: Binary Tree Inorder Traversal

Recursive solution:

```swift
func inorderTraversal(_ root: TreeNode?) -> [Int] {
    if let node = root {
        return inorderTraversal(node.left) + [node.val] + inorderTraversal(node.right)
    }
    return []
}
```

Iterative solution:

```swift
func inorderTraversal(_ root: TreeNode?) -> [Int] {
    var stack = [TreeNode]()
    var ar = [Int]()
    var node = root
    while !stack.isEmpty || node != nil {
        if node != nil {
            stack.append(node!)
            node = node?.left
        } else {
            node = stack.removeLast()
            ar.append(node!.val)
            node = node?.right
        }
    }
    return ar
}
```
DynamoDB で、条件付き更新 と トランザクション を組み合わせて、UNIQUE 制約を実現する方法

## はじめに

現状、DynamoDB では、 RDB で言うところの`UNIQUE制約`がありません。つまり「UserテーブルでEmailを一意になるように制約をかける」といったことができません。

正確に言うと、ハッシュキー属性にはUNIQUE制約があります。
この記事では、ハッシュキーにはUNIQUE制約があることを利用しつつ、`条件付き更新` と `トランザクション` を組み合わせて、任意の属性を対象とするUNIQUE制約を実現する方法を紹介しています。


以下のようなDynamoDBの知識を前提としています。

- 項目 と 属性 がなにを指しているのか理解している
- hash-key(とrange-key) を理解している
- 基本的な CRUD 関連の操作方法を理解している
- 条件付き更新を理解している
- トランザクションを理解している


必要に応じて、以下の AWS のドキュメントを参照してください。

- [DynamoDB コアコンポーネント](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html)
- [DynamoDB での項目の操作](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/WorkingWithItems.html)
- [条件付きの書き込み](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.ConditionalUpdate)
- [既存の項目の上書きを防止](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html#Expressions.ConditionExpressions.PreventingOverwrites)
- [条件付き更新](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html#Expressions.ConditionExpressions.SimpleComparisons)


## UNIQUE制約の実現方法

例えば、以下のような User エンティティがあるとします。

![diagram-4658271672369125146.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2278/72d930c4-08f9-b4e1-13cf-2cc4fa40dc80.png)


User エンティティをDynamoDBに新規作成する場合、以下の項目を作成する処理をトランザクションで実行します。

- User エンティティ自体を保存する項目(`エンティティ項目`)
- UserのEmail属性を UNIQUE属性にするための項目(`UNIQUE制約用項目`)

`エンティティ項目` では、EmailやNameなどのエンティティ自体の情報を記録します。
`UNIQUE制約用項目` では、UNIQUE制約をかけたい項目をhash-keyとして設定し、条件付き更新で試みます。

例として、Emailに対してUNIQUE制約をかけたい場合を考えます。このとき、`UNIQUE制約用項目`を以下の手順で作成します。

1. PK(hash-key) を `User#Email#test@example.com` という値で設定。
2. `if attribute_not_exists(PK)` で、書き込みを試みる。

以下の図は、UNIQUE制約に引っかかってエラーが起こる場合を示しています。

![dynamodb-timeline-summary.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2278/6ef3849f-9cd6-4ebc-11a2-25ad4fbc9ee4.png)

Bob が `test@example.com` で項目を作成した後に、Alice が `test@example.com` で項目を作成しようとして失敗します。 Aliceが書き込むときには `if attribute_not_exists(PK)` の条件が偽になるからです。

トランザクションで実行された場合、ロールバックが実行され、Aliceの項目作成処理がキャンセルされます。

このようにして、UNIQUE制約を実現しています。


## 更新と削除の処理について

上記は、新規作成時の処理について解説しました。更新と削除のときにも注意が必要です。
それぞれ以下のような処理を行います。

### 更新時

更新の場合は、__Emailの値を変更する場合のみ__ UNIQUE制約について考慮する必要があります。
以下の更新処理をトランザクションで実行します。

- `エンティティ項目`のEmail属性の値を更新する
- 新しいEmailについて、`if attribute_not_exists(PK)` という条件で書き込みを試みる
- 古いEmailについて、`UNIQUE制約用項目`を削除する



### 削除時

削除の場合は、以下の処理をトランザクションで実行します。

- `エンティティ項目`を削除する
- `UNIQUE制約用項目`を削除する


## まとめ

現状、DynamoDBでは任意の属性に対してUNIQUE制約をかけることができないので、条件付き更新 と トランザクションを組み合わせて擬似的に実現する方法を紹介しました。

「hash-key に設定できないけどUNIQUE制約を設定したい属性がある」といった場合に、有効な方法であると考えています。デメリットとしては、実装が少し複雑になってしまうところでしょうか。

DynamoDBは、アップデートされるごとに機能が増えたり、機能の制約が緩和されたりするので、将来的に UNIQUE制約を設定できる可能性もあるかもしれません。そうなった場合は、この方法は不要になるでしょう。
vue cliでプロジェクト作ったら（メモ）

#前記事のURL
https://qiita.com/s12ac098/items/f24ac76167b3d846064e

#プロジェクトのディレクトリで「run npm serve」
![npmrundev.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244716/5014af34-d549-d72f-c9ef-ccba8e618db2.jpeg)

#localhost:8080にアクセス
![runserve.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244716/e8d6f60d-73c4-db69-2d94-e8fdf826d45c.jpeg)

#デフォルトのプロジェクトができます
![default.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244716/34216b0a-c54b-ba52-706e-b588e4039b42.jpeg)

#デフォルトをいじる　Part1～HelloWorld.vueのリネーム～
まずcomponentsのHelloWorld.vueをリネームしましょう（ダサいから）
![helloworld.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244716/fa37889e-7a55-ac54-c613-76eaa3f63943.jpeg)

安心してください。ページが死ぬだけです。
![compile.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244716/ec9b8ca0-12d2-643b-1449-85db544fb632.jpeg)

App.vueにHelloWorldがいっぱいいるので、全部indexに変えましょう。
![changealloccurences.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244716/e2f70c72-75ff-af54-5e66-c4b12bb24a79.jpeg)

```App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <index msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import index from './components/index.vue'

export default {
  name: 'app',
  components: {
    index
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

#デフォルトをいじる　Part2～ページをまっさらに～
つづいて、こいつを真っ白に染めましょう
![default.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244716/6bb466c1-f5ba-5c90-edca-433804cc63d0.jpeg)

divタグとstyleタグの中を消しましょう。

```App.vue
<template>
  <div id="app">
　　　<h1>vue cliがまっさらに・・・</h1>
  </div>
</template>

<script>
import index from './components/index.vue'

export default {
  name: 'app',
  components: {
    index
  }
}
</script>

<style>

</style>

```

index.vueの中も同様にですね。※divタグのクラスはご自由に

```index.vue

<template>
  <div class="index container">

  </div>
</template>

<script>
export default {
  name: 'index',
  props: {

  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>

</style>
```

![white.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244716/c82eabb1-2a7f-406b-cce1-79b4a570bb44.jpeg)


#つづく
次回はcomponentの追加における３ステップについて！
PHPのincludeを簡単に非同期化するLazy Includeコンセプト

PHPで別ファイルのHTML部品を読み込む`include`を、できるだけ簡単にJavaScriptによる非同期読み込みに変えちゃおうという試みです。名付けて`Lazy Include`。

php-lazy-include
https://github.com/miyanaga/php-lazy-include

画像の遅延読み込み`Lazy Load`もちょっとしたHTMLとJavaScriptのトリックですが、それをHTMLの断片にまで拡張したものです。

※ 上記のソースコードは実用的なライブラリではなく、コンセプトの実装例です。ぜひ改良してみてください！

# コンセプト

ソースコードはよく見るPHPの`include`です。

```php:index.php
<div>Main File</div>
<?php include('includee.php') ?>
```

`include`される側のファイルも通常通りHTML断片を出力するPHPですが、先頭と末尾に1行ずつ決まったおまじないが記述されています。

```php:includee.php
<?php if(include('lazyInclude.php')) return ?>
<div>Sub File</div>
<?php endLazyInclude() ?>
```

## 結果

上記のソースが実行されると、次のようなHTMLとJavaScriptに展開されます。

`include`を行った場所にひとまず目印となる`div`要素を置いておき、`DOMContentLoaded`イベントでそこに元々`include`されるはずだった内容を展開するという流れです。

```html:index.php
<div>Main File</div>
<!-- 非同期にincludee.phpの内容を展開する目印 #the-lazy-include -->
<div class="lazy-include" id="the-lazy-include"></div>
<script>
/* <script src="/includee.php?id=the-lazy-include"> をbody末尾に追加 */
window.addEventListener('DOMContentLoaded', function once() {
  window.removeEventListener('DOMContentLoaded', once);
  var script = document.createElement('script');
  script.setAttribute('src', "\/includee.php?id=the-lazy-include");
  document.body.appendChild(script);
});
</script>
```

`body`に追加された`script`要素は次のJavaScriptを読み込んで実行します。

```javascript:includee.php
/* 目印 #the-lazy-include にincludee.phpの本来の内容を展開 */
document.getElementById("abc").innerHTML = "<div>Sub File<\/div>\n";
```

2行のおまじないを追加すると、JavaScriptによる`非同期include`になり、そのおまじないを除去するとPHPによる普通の`同期include`に戻るというものです。

# 何が嬉しいの？

ページの読み込み直後のレンダリングから、`Lazy Include`したDOMを除外することで表示の高速化を図っています。

「[PageSpeed Insightsの点数はどのように計算されているか。100点をとるための条件](https://qiita.com/miyanaga/items/d38124cdd64a1999fed9)」という記事で、PageSpeed Insightsの点数においてはファーストビューの描画時間が重要であると書きました。

このHTMLデータ自体の軽量化もさることながら、初期のDOMのオブジェクト数を減らすことはPageSpeed Insightsの点数アップにもよい影響が期待できます。

そのような非同期処理が、JavaScriptの記述不要で簡単に実現できます。

# ユースケース - ボリューム感のあるフッター

フッターにサイトマップをまるごと掲載するサイトが増えています。サイトによってはクローラー向けの内部リンク目的だったり、デザイン上どっしりボリューム感を出す目的かもしれませんが、`ユーザーにとっては無駄の多いコンテンツ`です。

* たまに役立つかもしれないがそこまで滅多にスクロールしない。
* 大規模サイトだとけっこうなHTMLの量とDOMオブジェクトの数がある。
* ほとんど変更されないのに毎回毎回、HTMLに含まれて送信される。

もしSEO上の意図がないのであれば、Lazy Includeによって少し後でレンダリングすることで次の効果が期待できます。

* 読み込みとファーストビューの描画が速くなる。
* JavaScriptのキャッシュでブラウザにキャッシュを持たせることもできる(上記コードでは`Expires`ヘッダは未実装)
応用数学(線形代数)

※以下、個人的な勉強のためのレポートです。
※間違い多々あると存じますが、現在の理解レベルのスナップショットのようなものです。
※勉強のためWebサイトや書籍からとても参考になったものを引用させていただいております。
#線形代数について
- 「5」、「-3」、「1.5」などのように、*大きさのみ*を持つ量を_スカラー(scalar)_という。
- 一方、*大きさと向き(角度)*を持つ量を_ベクトル(vector)_という。
$$
\begin{bmatrix}
100 & \pi
\end{bmatrix}
$$
$$
\begin{bmatrix}
30 & 40i
\end{bmatrix}
$$
電気数学などで用いられる複素平面などはその例であるが、ベクトルは別に2値をまとめたものというわけではなく、共通の要因をひとまとめにしたものであればよく、
$$
\begin{bmatrix}
3 & 4 &5
\end{bmatrix}
$$
や
$$
\begin{bmatrix}
3 \\\
4 \\\
5
\end{bmatrix}
$$
といった記法をとることもできる。行ベクトル(横ベクトル)、列ベクトル(縦ベクトル)

- 行ベクトルを縦に、列ベクトルを横に並べたものを行列(matrix)という。

-　線形代数はこの行列の演算を扱う数学の分野である。線形代数はInformation Science分野において応用として用いられている。コンピュータグラフィクスの分野で用いられる_線形写像_、以下本稿で記述する固有値解は線形代数学が扱う代表的なトピックである。

#固有値・固有ベクトル・固有値分解について
- ある行列_A_について

```math
A\vec{x} = λ\vec{x}\\
```
が成立するとき、
行列_A_の固有値を_λ_、固有ベクトルを$\vec{x}$という。

- これは「どんな一次変換でも、必ず向きが変わらないベクトルが存在する」つまり、「もとのベクトル$\vec{x}$を行列_A_によって一次変換したベクトルが、定数_λ_倍したものとなっている」ことを示す。正方行列には固有値と固有ベクトルが存在する。

- ある行列の固有値と固有ベクトルを求めることを、固有値分解という。

- ある行列を固有値分解することで、その行列の特徴的な性質をとらえることができる。このことにより、異なる行列_A_と_B_の固有値分解を行い、類似度を調べることなどが可能になる。

#特異値・特異ベクトル・特異値分解について

- 上述したように、固有値分解は正方行列にのみ適用できるものである。しかしながら、自然言語処理における単語データや、画像解析における画像処理データなどはたくさんの要素を持つ矩形行列である。そのような矩形行列データの分析に固有値分解に類似した手法として用いることができるのが、特異値分解である。
- _M_を矩形行列とし、ある非負の実数σをおく

```math
M\vec{v}=σ\vec{u}\\
M^T\vec{u}=σ\vec{v}
```
この条件を満たす単位ベクトルがあるとき、実数σを行列_M_の特異値_(singular value)_と呼び、$\vec{u}$を左特異ベクトル_(left-singular vactor)_、$\vec{v}$を右特異ベクトル_(right-singular vactor)_と呼ぶ。
- この特異値分解の手法を用いることにより、正方行列の特徴的性質の調査に使った固有値分解の手法を矩形行列に持ち込むことが可能になる。

- googleのページランクのアルゴリズムにも、これら「行列」や「線形代数」、「固有ベクトル」といった数学的手法が取り入れられている。単純なリンク数といったスカラー量だけではなく、リンクの方向や重要度の高いページからのリンクについてweightを加味するなどといった「本当に重要なページを検索上位にもってくるために、Webページをデータとしてとらえた場合、どのように分析すれば有益な価値として比較できるのか」を考慮したアルゴリズムにも使用されている。

**引用**
「マンガ　線形代数入門」鍵本聡　北垣絵美
「マンガでわかる線形代数」高橋　信
線形代数って何？https://oguemon.com/study/linear-algebra/hello-world/
電磁気学/ベクトル解析https://www.agr.nagoya-u.ac.jp/~mechbio/lecture_denjiki_vector.html
ベクトルと行列の定義http://www.snap-tck.com/room04/c01/matrix/matrix01.html
ラビットチャレンジhttp://ai999.careers/rabbit/
【Swift】loadViewの注意点


loadViewを使用した際に困ったことを、備忘録として記載しておきます。

# 困ったこと
StoryBoardを使用することになった時に、loadViewを使ってレイアウトしていたせいで、作業が詰んでしまいました。

# loadViewの呼ばれるタイミング
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f34353532352f36373064303033382d366630332d303935662d636132322d3930633531306638626162662e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/186535/1fac0917-7c9a-7208-0149-08f43580f2b7.png)
引用：[UIViewControllerのライフサイクル](https://qiita.com/motokiee/items/0ca628b4cc74c8c5599d)

loadViewするタイミングで、controllerが制御するviewの作成を行います。

# loadViewの使用目的
- xibを利用せず、コードでViewを作成する場合はオーバーライドする
- コードでViewを作成する場合はloadViewにコーディングをする※ただし、UI部品のセットはこのメソッドでなくても問題ない

#loadViewの注意点
- StoryBoard(Interface Builder)やxibを使用する場合は、loadViewはオーバーライドしてはいけない
- 当たり前といえば当たり前ですが、loadViewの中身を書かなくても、オーバーライドしているのでアウトです。

```Swift
// UI 部品を View へセットする場合はこちらをオーバーライドします。
// ただし、UI 部品のセットはこのメソッドでなくても問題ありません。
override func loadView() {
    super.loadView()
    print("loadView")
}

// 初期表示時に必要な処理を設定します。
override func viewDidLoad() {
    super.viewDidLoad()
    print("viewDidLoad")
}
```
引用：[【Swift】UIViewController ライフサイクル 簡易説明書 | ポケットリファレンス サンプル付き](https://blog.77jp.net/swift-uiviewcontroller-life-cycle)

loadViewを使うときは、StoryBoardやxibを使用しないか、きちんと確認しましょう。

#参考リンク
- http://buchi.hatenablog.com/entry/2014/09/19/143938
- -[【iOS】【Swift】太り過ぎなUIViewController.viewDidLoadをスリムにして可読性を爆上げする](http://blog.penginmura.tech/entry/2018/02/12/163711)
- [UIViewControllerまとめ](https://qiita.com/edo_m18/items/189acd18f1ecc368b5b0)
プログラミング言語の本の選び方 coding(155)

プログラミング言語の本を選ぶときの方法を記録します。

最近だと、新しい言語を覚えるのに、必ずしも本を購入する方法を取っていません。

ちょっと前まで取っていた方法です。

# ソースコードデータ付きかどうか
CDでも、Webでもどんな方法でも電子的にあるかどうか。
本を買ったらついてくるパスワードが必要でも、電子的に入手できれば途中の手間はさほどかまわない。

どんなプログラミング言語でも、手当たりしだい動かして、振る舞いを見たい。

自分で入力するのを否定するわけではない。
次の項目で、写経として、紙しかないソースコードを入力したことは何度もある。

ソースコードデータ付きの本は、選ぶのではなく、まず１０冊動かして見る。
動かして見ると、優劣がはっきりわかる。

異なる機材、異なるOS、異なる言語の版向けのソースがついていると、
それを自分の持っている機材、OS、言語の版に合わせようとする作業で、
コンパイルエラーを取るのが勉強になる。

内容の良し悪しより、そっちの方が大事。
amazonで、けなされている本があるが、この方法で使うと、役にたつものもある。
他の本に掲載されていないソースがついて入れば神。

# ソースコードが全体の１割以上を占めているかどうか。
できれば文字数の３分の１がソースコードが嬉しい。

電子的にソースコードがついていなくても、書籍の３分の１以上がソースコードならよい。

LINUX Core Kernelコメンタリーオープンソースコード詳解
![5161JG0V7AL._SY353_BO1,204,203,200_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/7943077c-d32b-ff8d-604f-d9d60ced9307.jpeg)
https://www.amazon.co.jp/dp/4797820063/

Linux kernelは入手できるので、もう一つ上の分野かもしれない。

ソースコードが付いている本は、そのソースコードを打ち込むだけでなく、
他の言語に変換しながら打つということもすることがある。

最初にコンパイラを勉強したときに、Pascalで書かれていたコンパイラの本のソースを
C言語に変換しながら入力し、PascalとC言語の違いを理解しながらCプログラミング言語を覚えた。

C言語の教育では、
Lode-Runnerで学ぶ実践C言語-ビー・エヌ・エヌ企画部
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f35313432332f62356564336231632d376133322d353139642d386364382d3439663832383663623964332e6a706567.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/75193d71-35aa-9af3-d50d-d286e66003c2.jpeg)

https://www.amazon.co.jp//dp/4893690116
を入力してもらうこともある。

自分で入れて、コンパイルエラーがなくなる頃には、C言語のほとんどの文法とコンパイルエラーの取り方がわかるらしい。

Cパズルブック   Alan R. Feuer ,訳： 田中 和明, 手塚 忠則
https://www.amazon.co.jp/dp/4877830294
![51QQZNVK6JL._SX374_BO1,204,203,200_-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/d16de11f-f66b-be23-8a95-6e7b0b82cd30.jpeg)

# プログラミング言語の書き方、考え方がわかる本
CODE COMPLETE 第2版 上 完全なプログラミングを目指して
![51E1DYKHW7L._SX384_BO1,204,203,200_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/bdbba551-41b8-34ec-8dbc-c5f5607e1d88.jpeg)
https://www.amazon.co.jp/dp/489100455X


ジャイルサムライ−達人開発者への道,
Jonathan Rasmusson, 訳：西村 直人, 角谷 信太郎, 近藤 修平, 角掛 拓未, 2011
https://www.amazon.co.jp/dp/4274068560/
![51flKufOVUL._SX346_BO1,204,203,200_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/0db5b108-f543-7019-3cee-826493e1fbdb.jpeg)


# 最近

本を買わずにプログラミング言語を覚えるときは、

1. 勉強会に参加　現地で手を動かしてコンパイルエラーの取り方などを教えてもらう
2. ネットの動画拝聴　主に英語の動画を見る
3. ネットのソースコードを動かす　Qiitaを含む

まだ、この方法でNativeに近い習得をした言語はない。新しい言語での仕事がない。ごめんなさい。

# 参考資料(reference)
６５歳からのプログラミング入門
https://qiita.com/kaizen_nagoya/items/1561f910c275b22d7c9f

プログラミング言語教育のXYZ
https://qiita.com/kaizen_nagoya/items/1950c5810fb5c0b07be4


# 文書履歴(document history)
ver. 0.01 初稿 20190503
ver. 0.02 URL追記　20230214

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.