OmniAICreator/Qiita-1.07M huggingface dataset:
プリザンターから自前アプリの画面を開く

# 概要
プリザンターから情報を引き継いで、自前アプリの画面を開く方法を調査。
例えば、プリザンターでログインした後に、特定のデータだけは自前アプリを作って表示するといった使い方を想定。

## 前提条件
- 環境
    - OS: Windows10
    - ローカル環境に構築したプリザンター
- 以下の詳細説明は省略
    - プリザンター
    - php

# 結論
プリザンターから自前アプリの画面を開けることを確認できた。
スクリプトでPOSTして自前アプリに画面遷移させる方式。
プリザンターの情報の引継ぎも可能。

# 詳細

## 自前アプリを準備
phpで簡単なページを作って、簡易サーバを起動しておく。
POSTで受け取った以下3つの情報を表示するだけの画面。

- userId
- userName
- loginId

↓簡単なページ

```index.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test</title>
</head>
<body>
    <h1>Test Page</h1>
    <p>
        userId: <?= $_POST['userId'] ?><br/>
        userName: <?= $_POST['userName'] ?><br/>
        loginId: <?= $_POST['loginId'] ?><br/>
    </p>
</body>
</html>
```

↓簡易サーバ起動

```
>php -S localhost:8030
```

## プリザンターにスクリプトを設定

プリザンターにフォルダを作成し、スクリプトを追加。
フォルダを開いたときに、自前アプリにPOSTするスクリプト。
プリザンターで用意されている3つの情報をPOST。

↓フォルダを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273897/d22f1d8a-0eef-2428-df49-12060a86bde2.png)

↓スクリプトを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273897/8cc0bac0-9c91-60ec-267f-0449621e2aba.png)

↓スクリプトのソース

```post.js
let url = 'http://localhost:8030/index.php';
// POST用のフォームを生成
let html = '<form method="post" action="' + url + '" id="form_post" style="display: none;">';
html += '<input type="hidden" name="userId" value="' + $p.userId() + '" >';
html += '<input type="hidden" name="userName" value="' + $p.userName() + '" >';
html += '<input type="hidden" name="loginId" value="' + $p.loginId() + '" >';
html += '</form>';
// bodyに追加
$("body").append(html);
// POSTで送信
$("#form_post").submit();
```

## 動作確認
ログアウトして、再度ログイン。
「他のページに遷移」のフォルダを開くと、自前アプリの画面が表示されることを確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273897/be6a5225-0320-714a-be52-eaad6dcce273.png)

↓フォルダを開くと。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273897/ce78b820-4ddc-d291-7d98-f8244c7a731a.png)

ログインユーザの情報を自前アプリで表示できることを確認できた！

## 補足
上記のスクリプトを設定すると、フォルダ自体の設定ができなくなるので注意。
設定したいときはURLを直指定で設定画面を開くこと。
URLの例: http://192.168.10.10/pleasanter/items/12423/edit
TableViewのCell再利用について

##はじめに
TableViewはスクロールするたびに新しいCellを作っているわけではないみたいです。
勉強始めたてのころはCellが新しく作られているのか、それとも再利用されているのかという疑問も持たないかもしれません。（私がそうでした）
しかし、実際に使っていく中で、この辺りを理解しておいた方がいいと思い知らされたので記事を書いてみます。

##なぜ再利用するか
パフォーマンスが低下するから！みたいです。
新しいCellを作成していたら、スクロールすればするほどCellが作成されるのでよくないみたいです！（１００個も２００個も作ってられない）
再利用の場合、画面の外に行ったCellを使うことで必要なCellの数が抑えられるからです。

##セルの登録
カスタムセルをコードで書く場合は
```register(_:forCellReuseIdentifier:)```
をviewDidLoadなどで呼んで登録しておく必要があるみたいです。
Storyboard上でカスタムセルを定義している場合はいらないらしいですよ。
この登録はreuseIdentifierにIDを入力してIDで管理することができます。
（画像のIdentifier）
![スクリーンショット 2020-11-16 6.56.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/467ad69f-4681-73b9-0d2b-af37467b12a6.png)



##セルを再利用する
ここからが本題です。
実際にセルを再利用する時は、スクロールして画面表示外からセルが現れる時です。
ですので、セルを生成するための処理の中に再利用のコードを書く必要があるわけです。
セルが作成されるのは
```tableView(_:cellForRowAt:) ```
の中です。
この中にセルを再利用するコード
```dequeueReusableCell(withIdentifier:for:)```
を書いて、セルを生成する時に再利用できるセルがあれば再利用してください🙇‍♂️っていう指示を書きます。
この時の再利用可能なセルはreuseIdentifierで紐付けしたものになります。

##画面外に行った再利用待ちのセルはどこへ？
Reuse QueueというものをtableViewは持っていて、これはreuseIdentifierごとに存在しています。
上の画像で言うと、IdentifierがCell1なのでCell1用のReuse　Queueが存在しています。
再利用できるものをID別で入れておく在庫置き場の様なものですね。
画面外に行くと、セルは自分のIDのReuse Queueの中に入り、同じIDのセルが必要になった時に取り出されます。

##セルは再利用したいけど、セルの内容に変更の処理を行いたい時
セルの見た目が変更されたままReuse　Queueの中に入り、変更が残ったまま再利用されることがあります。
そこで使用するのが
```prepareForReuse()```
です。
ここにセルの変更内容を初期状態に戻す処理を書くことで、初期状態のセルを再利用することができます。

##最後に
セルの再利用についての記事を書きました。
tableViewは頻繁に使うので仕組みも理解していた方が良いそうです。
今回初めてQiitaで記事を書いてみたので良いアウトプットになりました。
間違っている箇所などありましたらご指摘ください。
わかりやすいコード例とかができましたらまた載せていきます。

##参考記事

https://medium.com/@shiba1014/uitableviewcell%E3%81%AE%E5%86%8D%E5%88%A9%E7%94%A8%E3%82%92%E7%9F%A5%E3%82%8B-24f00d68f17d

https://fluffy.es/solve-duplicated-cells/
Base64以外のBase〇〇系紹介

バイナリーをASCIIコードで表現可能なテキストに変換するためのエンコーディングであるBase64はインターネットの様々な箇所で使われています。

ですが、Base64以外にもBase〇〇系は数多くあることを知っている人は少ないと思います。
この記事ではあまり陽の当たらないそれらのエンコーディングを紹介します。

# Base32, Base16
最初に紹介するのはBase64と同じRFCに載っているBase32とBase16です。

https://tools.ietf.org/html/rfc4648

Base64が6ビットごとにバイナリをテキストに変換していたのに対して、これらはそれぞれ5ビット、4ビットごとに変換を行います。
Base64は6ビットを1文字のASCII(8ビット)に変換するため、変換前後でデータ量は33%増加する一方でBase32は60%の増加、Base16は100%もの増加をします。
これらはBase64と比較した場合にデータ量の増加が激しいですが、必要とされる文字数を少なくできるという利点があります。
そのため、人間が読み書きするときに判別しづらくなる文字や、一部のシステムで特殊な扱いを受ける文字(UNIXパス区切り文字である/など)を除外することができます。
実際にRFC4648ではアルファベットのI, B, Oと区別しづらい1, 8, 0の数字が除外されています。

Base32はジオコーディングのアルゴリズムであるジオハッシュで使われています。
なお、このBase32はRFC版と文字列セットが多少異なる亜種です。
RFC版とは逆にI, B, Oを除外して替わりに1, 8, 0が使われています。
https://en.wikipedia.org/wiki/Geohash#Algorithm_and_example

# Base58
次に紹介するのはBase58です。
エンコーディング後の文字列が58種類になるのが特徴で、ビットコインアドレスの表記に使われています。
https://en.bitcoin.it/wiki/Base58Check_encoding#Base58_symbol_chart

Base64と比較した場合、人間が判別しずらい文字が取り除かれているという利点があります。
例えば数字の0とアルファベット大文字のOは除外されアルファベット小文字のoが採用されています。
また、Base32と比較した場合には、効率がよいという利点があります。
Base58は元のバイナリと比較して37%しかデータ量が増加しません。

ただし、Base58の欠点もあります。
文字種の数が2の累乗にならないため、エンコーディング・でコーディング処理のオーバーヘッドが大きいです。
ビットコインの参考実装ではバイナリを整数に変換してから、愚直に商と剰余を求めています。
この処理はBase64やBase32のエンコーディングと比較するとかなり大きなオーバーヘッドになります。
Base64も商と剰余を求める必要がありますが、除数が2の累乗(64=2^6)でありビット演算を使うことで効率化できていた部分が効率化できなくなったためです。
多くのCPUではビット演算よりも除算のほうがより多くのクロックサイクルを要します。
https://www.agner.org/optimize/instruction_tables.pdf

また、参考実装でのこの部分にも注意が必要です。
エンコーディングしたいデータを一旦整数に変換するため、エンコーディングしたいデータに比例するワーキングメモリが必要になります。

```
x = convert_bytes_to_big_integer(hash_result)
```

ビットコインアドレスは200ビットしかないためこれらの欠点の影響は少ないですが、大容量のデータをBase58でエンコーディングするとこの欠点は顕著になります。

# Base85
最後に紹介するのはBase85です。32ビットのバイナリデータを5文字のASCIIコード文字に変換します。このエンコーディングは他ほどしっかりとした標準化がされているわけではなく、様々な亜種が存在します。特に有名な亜種であるAscii85が最もよく使われているのはPDFです。

https://en.wikipedia.org/wiki/Ascii85

さて、なぜ85なんて中途半端な数が使われるのでしょうか。空白や改行などの、転送途中で損失する恐れがある文字を除くと、安全に使うことができるASCIIコードの印刷可能文字は95種類あります。そして、

```math
\log_{95}{2^{32}} = 4.87
```

であるため、5文字の組で32ビットのデータを十分に表現できることが分かります。では、必要十分な文字種の数はいくつになるのでしょうか。それは以下の式を満たす最大の整数 $n$ であり、答えが85でした。

```math
\log_{n}{2^{32}} < 5
```

Base85の利点はやはり効率の良さです。元のバイナリと比較して25%しかデータ量が増加しません。今まで紹介した中では最良の効率です。
また、2の累乗個の文字数を使っているわけではないですが、入力は32ビットを1単位として行うことができるので、Base58にあった時間複雑度や空間複雑度の欠点もありません。

一方で、Base85の欠点は多くの文字種を入れたことにことで、 `\` や `"` などのシステムによっては取り扱いに注意を要する文字が含まれることです。
そのため、Z85などの亜種では問題になりそうな記号類を取り除いた文字セットを使用しています。
https://rfc.zeromq.org/spec/32/

# まとめ
さて、Base64以外のBase〇〇系を紹介しましたが、やはり一番バランスが良いのがBase64になるかと個人的には思います。
Base32とBase16はエンコーディング後のデータ量の増加という欠点があり、Base58はそれに加えてエンコーディング処理のオーバーヘッドの高さが目立ちます。
またBase85は効率を求めるあまり取り扱いに注意を要する文字が混入する確率が上がるため、汎用性に欠けます。
そのため、Base64が一番よく使われているのだと思います。
HereRocksなるものがあるらしい

# hererocks のメモ

なにやらLuaRocksの上位互換らしきものがあるらしいので、それについてのメモ。
Windowsでも簡単にLuaRocksが扱えるとのこと。

[Github](https://github.com/luarocks/hererocks)

## 概要

Githubには以下のように記載がある。

> hererocks is a single file Python 2.7/3.x script for installing Lua (or LuaJIT or moonjit or RaptorJIT) and LuaRocks, its package manager, into a local directory. It configures Lua to only see packages installed by that bundled version of LuaRocks, so that the installation is isolated.

ローカルファイルにLuaやその派生言語、およびLuaRocksをインストールするためのPythonスクリプトとのこと。つまりPythonがないと始まらない。
メンテナンスもLuaRocksのチームが担っているらしい。
なんでもいいやとりあえず落とせ落とせ。

## 実行環境

必要なもの：

- Python 2.7 or 3.x
- Git
- コンパイラ
  - Windows: MinGW + gcc (PATHを通してあること)、あるいはVisual Studio 2008 or later
    - (2020年11月27日追記) MSVC 2015 までっぽい
  - OS X: cc
  - その他: gcc

```PowerShell
PS C:Users\hogehoge> pip -V
pip 20.2.4 from C:users\hogehoge\appdata\local\programs\python\python39\lib\site-packages\pip (python 3.9)
PS C:Users\hogehoge> python -V
Python 3.9.0
PS C:\Users\hogehoge> mingw-get.exe -V
mingw-get version 0.6.3-pre-20170905-1
Copyright (C) 2009-2013, MinGW.org Project
```

## インストール

`pip`でインストールする。
`pip install git+https://github.com/luarocks/hererocks`と打てば数秒で終わる。

```PowerShell
PS C:\Users\hogehoge> pip install git+https://github.com/luarocks/hererocks
Collecting git+https://github.com/luarocks/hererocks
  Cloning https://github.com/luarocks/hererocks to c:\users\hogehoge\appdata\local\temp\pip-req-build-9p8s_l6u

#    ⋮　

Successfully installed hererocks-0.22.0

PS C:\Users\hogehoge> hererocks.exe --help
usage: hererocks [-l LUA] [-j LUAJIT] [-m MOONJIT] [--raptorjit RAPTORJIT] [-r LUAROCKS]
                 [--show] [-i] [--compat {default,none,all,5.1,5.2}] [--patch]
                 [--cflags CFLAGS]
                 [--target {linux,macosx,freebsd,mingw,posix,generic,mingw,vs,vs_XX,vsXX_YY}]

#    ⋮
```

## Luaのインストール

Lua自体は元々インストールされているが、hererocksで管理しておきたいのでやっておく。
`hererocks.exe lua53 -l 5.3 -r latest`でlua5.3がインストールされる。

```PowerShell
PS C:\Users\hogehoge> hererocks.exe lua53 -l 5.3 -r latest
Fetching Lua 5.3.6 (target: mingw) from http://www.lua.org/ftp/lua-5.3.6.tar.gz
Verifying SHA256 checksum
Building Lua 5.3.6 (target: mingw)
No patches available for Lua 5.3.6
Installing Lua 5.3.6 (target: mingw)
Fetching LuaRocks 3.4.0 from http://luarocks.github.io/luarocks/releases/luarocks-3.4.0-win32.zip
Verifying SHA256 checksum
Building and installing LuaRocks 3.4.0
Done.
```

なんか勢いでユーザーフォルダ直下に落としてしまった。まいっか。
このままだとPATHが通っていないので、通しておくこと。

## LuaRocks で make

本題。とはいえ使い方はいたって普通。
LuaのPATH(`\lua5x\bin`)を通してあれば普通に使える。

```PowerShell
PS C:\Users\hogehoge\Path\To\rockspec> luarocks make

mymodule scm-1 depends on lua >= 5.1 (5.1-1 provided by VM)
C:\mingw\bin\gcc.exe -O2 -c -o src/mymodule.o -IC:\Users\hogehoge\lua51\include src/mymodule.c
C:\mingw\bin\gcc.exe -shared -o mymodule.dll src/mymodule.o C:\Users\hogehoge\lua51\bin/lua51.dll -lm
mymodule scm-1 is now installed in c:\users\hogehoge\lua51\ (license: MIT/X11)
```
オブジェクトに何かを代入している処理を探す正規表現



訳あって、ツクールMVのプラグインの中から循環参照を探すことになった。
この場合、オブジェクトに代入処理をしているすべての処理を探り、その中から犯人を捜すことになる。
代入処理をすべて検索するには以下の記述を使う。

```:
this\.(.*)( *)=( *)([^true|false|\d| new (.*)].+)
```
これは最適化もしてないし、否定条件は使いながら書き換えている。
もちろん他の代入パターンも考えられるが、基本的にはこれで問題ないはずである。

テストに使用したデータは以下の通り。

```:
this.aaa =baa
this.bbb = baa
this.ccc=ccc

this.boo()
this.xxx = true
this.yyy = false
this.zzz =19
this.nnn = new hoge()
this.nnn = new hage(xxxx)
```
Appの設計アイデア

招待ポイントプレゼント

「招待コード」を友達にシェアし、ポイントがゲットするから、

ユーザーが友達にシェアするの意識が高めていく。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471610/d89e5522-f16f-9e93-b99f-cbf1eea8c8fe.png)


マイページで自分のプロフィール写真などを編集できる
ニックネームを設定したり、写真をアップロードしたり、SNSみたいな機能があれば、顧客のロイヤリティを高めていく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471610/6efea3d9-2788-2d4e-f857-b2d6083ccb28.png)


見た目としては、今はやっているアプリが多数メニューを一番したにおきます(ボトムナビゲーションバー 英語：Bottom navigation bars)
こちらも参考になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471610/dcd8c811-de54-566b-5cf6-b2015f0b5e7f.png)
JDBI3でInputStreamをBindしたい時

## JDBI2ではできたのに

```java
@SqlUpdate("update samples set file = :file where flag = true")
int updateFile(@Bind("file") InputStream file);
```

```kotlin
@SqlUpdate("update samples set file = :file where flag = true")
fun updateFile(@Bind("file") file: InputStream?): Int
```

JDBI3ではできなくなっている...

```
org.jdbi.v3.core.statement.UnableToCreateStatementException: No argument factory registered for type ...
```
のようなエラーが出てくる

GitHubでエラーメッセージを検索したところ、↓が怪しい

```java
return new UnableToCreateStatementException("No argument factory registered for '" + value + "' of qualified type " + qualifiedType, ctx);
```

https://github.com/jdbi/jdbi/blob/3c93a316d5cbf9507e668b62414daae759641e93/core/src/main/java/org/jdbi/v3/core/statement/ArgumentBinder.java#L174

どうやら、Bind対象のオブジェクトは Argument interfaceを実装している必要がある

（気が向いたら詳細追記）

## Bind用のInterfaceが用意されていた

解決策としては、InputStreamArgumentを使えば良い


```java
@SqlUpdate("update samples set file = :file where flag = true")
int updateFile(@Bind("file") InputStreamArgument file);
```

```kotlin
@SqlUpdate("update samples set file = :file where flag = true")
fun updateFile(@Bind("file") file: InputStreamArgument?): Int
```

http://jdbi.org/apidocs/org/jdbi/v3/core/argument/InputStreamArgument.html

第一引数に、InputStream
第二引数に、Streamのサイズ
第三引数に、ASCIIか否かを渡す

```
public InputStreamArgument(InputStream stream,
                           int length,
                           boolean ascii)
Parameters:
stream - the stream to bind
length - the length of the stream
ascii - true if the stream is ASCII
```
Ruby で URL を作るときのエスケープ処理

`https://xxxx` といった文字列のURLに、 クエリパラメータをつけて URL を作る場合、 クエリパラメータは 特別な形に変換する必要があります。

JavaScript でいう `encodeURIComponent` を実行してやる必要があります。
これにより `+` は `%2B` に、 `&` は `%26` になります。

## 基本

Ruby では `CGI.escape` を使います。

```ruby
require 'cgi'

CGI.escape('+ &') # => "%2B+%26"
```

### 使用例

`CGI.escape` を使って URL を組み立ててみます。
ハッシュを使うなどいろいろと改善できるところはありますが、ここではシンプルなパターンを記載します。

```ruby
"https://samole.com?key={CGI.escape(value)}"
```

`key` に特殊な文字を使うことはまずないと考えて `value` のみ escape をしています。

`key` も escape する場合は、 
https://github.com/rails/rails/blob/3-0-stable/activesupport/lib/active_support/core_ext/object/to_query.rb が参考になります。


## その他参考

* [RailsでURLのクエリ文字列を組み立てるときはHash#to_queryを使うと捗る](https://web-salad.hateblo.jp/entry/2014/04/25/104615)
[Vue.js]関数の引数

<h1>関数に引数を与える</h1>
```html
<p>現在{{num}}回クリックされました</p>
//クリックするたび２足される
    <button v-on:click = "countUp(2)">クリック</button>

```
```javascript
js
data:{num:0}
methods:{
//これはjsと同じで因数を下の式に当てはめているだけ
      countUp:function(a){
              this.num+=a
                }
```


<h1>関数の引数eventをhtmlに渡す場合</h1>
```html
//マウスのX軸とY軸を表示
  <p v-on:mousemove = "mousePosition($event,5)">マウスのX軸とY軸を表示するよ</p>
    <p>x:{{x}}y:{{y}}</p>
```
```javascript
data:{x:0,y:0},
methods:{
//マウスの場所xとyに対して渡した数を割る
mousePosition:function(event,divide){
       this.x = event.clientX / divide;
       this.y = event.clientY / divide;
                }
```
<p>eventをhtmlに渡す場合 $event として渡す</p>
Rubyの継承と委譲

継承と委譲の使い分けについてあまりわかっていないのでまとめました。

## 継承
他のクラスから機能を引継ぎ、新たにクラスを作成することです。

### 例
Baseクラスからすべのたメソッドを引継ぎ、Fooクラスを作成する

```ruby
class Base
  def message
    'ok'
  end
end

class Foo < Base; end
  
foo = Foo.new
puts foo.message
# => ok
```

## 委譲
特定の処理（責任）を他のクラスのメソッドに委ねることです。

### 例
BaseクラスのmessageメソッドをFooクラスにmessageメソッドを委ねる

``` ruby
class Base
  def message
    'ok'
  end
end

require 'forwardable'
class Foo
  extend Forwardable
  attr_reader :mess

  def initialize
    @mess = Base.new
  end
  def_delegator :mess, :message
end
  
foo = Foo.new
puts foo.message
# => ok
```

## 継承を使う場面
### 役割が同じ
駆け出しエンジニアも、経験が豊富なつよつよエンジニアも、プログラマーという役割は一緒です。
なので、Progurammerクラスを継承し、機能をそのまま引き継ぐようにします。

``` ruby
class Programmer
  def initialize(type, langages)
    @type = type
    @langages = Array(langages)
  end

  def type_is
    puts "私は#{type}です。"
  end

  def langage_is
    str = ''
    langages.each do |lang|
      str += "#{lang} "
    end
    puts "私は#{str}の言語を扱えます"
  end

  def klass_is
    str = case self.class.name
    when 'TsuyoTsuyo'
      '強強エンジニア'
    when 'Kakedashi'
      '駆け出しエンジニア'
    end

    puts "私は#{str}です。"
  end

  private
  attr_accessor :type, :langages
end

class TsuyoTsuyo < Programmer; end

class Kakedashi < Programmer; end

tsuyo = TsuyoTsuyo.new('Backend', %w[C C++ Python Go Ruby])
tsuyo.type_is
tsuyo.langage_is
tsuyo.klass_is

kake = Kakedashi.new('Frontend', %w[HTML CSS jQuery])
kake.type_is
kake.langage_is
kake.klass_is

```

## 委譲を使う場面
### 役割は異なるが一部の機能を使いたい
プログラマーとデザイナーでは役割が異なります。なのでこの場合は委譲を使い、`type_is`メソッドのみをProgrammerクラスより譲り受けるようにします。

``` ruby
require 'forwardable'
class Programmer
  def initialize(type, langages)
    @type = type
    @langages = Array(langages)
  end

  def type_is
    puts "私は#{type}です。"
  end

  private
  attr_accessor :type, :langages
end

class Designer
  extend Forwardable

  def initialize(type, skills)
    @programmer = Programmer.new(type, nil)
    @type = type
    @skills = Array(skills)
  end

  def_delegator :@programmer, :type_is

  private
  attr_accessor :type, :skills
end

class IkeIke < Designer; end

ikeike = IkeIke.new('WebDesigner', %w[HTML CSS Adobe JavaScript])
ikeike.type_is # このtype_isメソッドは`Programmer` classから譲り受けたメソッド
```

## まとめ
ここまでお読みいただきありがとうございます。
自分のコードを見直す機会になればと思います。

自分は普段はRailsでwebサービスの開発を行っているが、委譲を使う場面があまりない気がします。
今までは何でもかんでも「継承！！」としていた自分がいたのも事実です。
継承関係がいいのか、委譲を使った方がいいのかの判断は難しいですが、今後は委譲を利用するという選択肢も含めた実装をしていこうと思いました。
CSSの厳選小技②

# CSSの便利すぎる小技を紹介
①に引き続き、今回も意外と知られていないかつ、便利すぎる小技を紹介していきます。
そして今回は、「スクロール」の小技に厳選しています。
それではみていきましょう！

## スムーズスクロール
ページ内リンクをクリックすると、リンク先へスルッと移動するもの！
これまではJSで実装してましたが、その必要なし！
そしてコードの記載もめちゃくちゃ簡単です。

```CSS
html{
 scroll-behavior: smooth;
}
```
これだけ！！めちゃくちゃ便利で快適なWebページが作成できます。
ただ、残念な点があるとしたらIEとSafariが非対応とのことです。

## スクロールスナップ
スクロールしたときにピタッと各エリアを表示させたいときに使うものです。
JSなしでスクロール位置を調整してくれます。
高さを100vhにすることでフルスクリーンレイアウトとして表示もできちゃいます。

```html
<div class="container">
  <section class="area">1</section>
  <section class="area">2</section>
  <section class="area">3</section>
  <section class="area">4</section>
  <section class="area">5</section>
</div>
```

```CSS
.container {
  overflow: auto;
  scroll-snap-type: y mandatory;
  height: 100vh;
}
.area {
  scroll-snap-align: start;
  height: 100vh;
}
```
簡単ですね。こんな感じで１２３４５のそれぞれのページにピタッと止まります。
なんて便利なんだ…。

## スクロールした時に要素を固定にする
ページをスクロールした時に、次の要素に到達するまで、指定した要素が固定表示されるものです。
文章量が多いコンテンツに重宝しそうです！

```html
<section>
  <h2>概要</h2>
  <p>コンテンツ内容………</p>
</section>
```

```CSS
h2 {
  position: sticky;
  top: 0;
}
```
上記だと、h2クラス全てのものが固定されます。
これも便利！！！

# 結論
JSを必要とするものがどんどん必要でなくなってきています。
JSも大変重宝しますが、CSSのコード１行で済むならそっちの方がいいですね
可読性も上がりますし、メリットだらけです。
また発見したら書き込みます！
C10K 問題を解決する Ruby のワンライナー

# C10K 問題とは

i18n と L10N は，それぞれ internationalization と localization の略称だ。
internationalization は綴りが長いので，「i」と「n」の間に 18 文字あるというところから「i18n」という表記が生み出された。L10N も同様。
なお，「i18n」が小文字で「L10N」が大文字なのはタイプミスではない。
参考：[国際化と地域化 - Wikipedia](https://ja.wikipedia.org/wiki/%E5%9B%BD%E9%9A%9B%E5%8C%96%E3%81%A8%E5%9C%B0%E5%9F%9F%E5%8C%96)

では，「c」で始まり「k」で終わり，間に 10 文字ある英単語としてどんなものがあるだろうか。
これが C10K 問題である[^c10k]。

[^c10k]: この記事はジョーク記事です。本当の C10K 問題はまったく違うものです。ごめんなさい。

# コード

まず，英単語が大量に集められたファイルがあるとよいのだが，幸い，Linux や macOS にはそういうファイルが存在する。
`/usr/share/dict` というディレクトリー内にたいていそういうファイルがあるので覗いてみてほしい。
私の macOS では `/usr/share/dict/words` が英単語リストだった。
1 行に 1 単語。これがただひたすら並んでいるだけのファイルだ。数えたら全部で 23 万語以上あった。

ここから正規表現で抜き出せばいい。Ruby なら 1 行で書ける。

```rb
puts IO.foreach("/usr/share/dict/words").grep(/^c.{10}k$/i)
```

[IO.foreach](https://docs.ruby-lang.org/ja/2.7.0/method/IO/s/foreach.html) にファイルパスを与えると，行とごとにブロックを評価するが，ブロックを与えない場合は Enumerator を返す。
それを [Enumerable#grep](https://docs.ruby-lang.org/ja/2.7.0/method/Enumerable/i/grep.html) でフィルタリングしてやるだけ。
`grep` に正規表現を与えると，マッチした文字列だけからなる配列ができる。

結果は以下のとおり。

```
concertstuck
countercheck
counterprick
counterstock
Czechoslovak
```

な，なんじゃこれは？
Czechoslovak は名詞で「チェコスロバキア人」，形容詞で「チェコスロバキア（人・語）の」だが，あとの単語は見たこともないものばかり。macOS 付属の『ウィズダム英和辞典』にも載っていない。

concertstuck はどうもドイツ語の Konzertstück と関係ありそうだ。
Konzertstück は音楽用語で「小協奏曲」などと訳されたり，外来語として「コンツェルトシュテュック」と呼ばれたりするようだが，音楽に疎いのでよく分からん。

残りの 3 語はすべて counter- が接頭辞になった複合語だ。

ネットで調べてもいまひとつよく分からないけど，「countercheck」は「対抗手段」とか「ダブルチェック」（二重に点検すること）というような意味があるっぽい。
「counterstock」はチケットなどの半券を指すぽい。
「counterprick」はなんだろうな？
Android File Permission 


# Manifest
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <uses-feature android:glEsVersion="0x00020000" android:required="true" />


# 起動後


```

    private static final int REQUEST_EXTERNAL_STORAGE = 787;
    private static String[] PERMISSIONS_STORAGE = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };

   void requestPermission() {
        // activityは、これを実行するアクティビティ
        // REQUEST_WRITE_PERMISSIONは、8bit以下の整数定数
 /* Context context = getBaseContext();
 if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
 PackageManager.PERMISSION_GRANTED) {
 // 以前に許諾して、今後表示しないとしていた場合は、ここにはこない
 String[] permissions = new String[] {
 Manifest.permission.WRITE_EXTERNAL_STORAGE
 };
 ActivityCompat.requestPermissions(this, permissions, REQUEST_WRITE_PERMISSION);
 } else {
 // 許諾されているので、やりたいことをする
 }*/

        int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (permission != PackageManager.PERMISSION_GRANTED) {
            // We don't have permission so prompt the user
            ActivityCompat.requestPermissions(
                    this,
                    PERMISSIONS_STORAGE,
                    REQUEST_EXTERNAL_STORAGE
            );
        }
    }


```
Laravelのget()とfirst ()が曖昧だったので取得データを見てみた

LaravelのDB検索した後のデータの扱い時、getとfirstの扱いが曖昧だったため確認して見ました。

###前提
例えばid、title、bodyを持つpostデータのテーブルがあったとします。
で、そのidを持つpostを検索し、そのpostのtitleを返すコントローラーを作りたいとします。

###最初の状態。get()でデータを取得した。
```php

public function post($id){
        $post = Post::where('id',$id)->get();//whereで引数の$idと同一のpostを検索。
        Log::debug($post);//このログの出力：[{"id":5,"title":"hoge","body":"hoge"}]
        return $post->title;
       }
//詳細は省略しております

```

が、上記のように「$post->title」を返そうとするとそんなプロパティないよ！と怒られエラーとなりました。

```php

local.ERROR: Property [title] does not exist on this collection instance.
```

なぜだ？ちゃんと出力データの中には「title」あるのに！と思ってgetやfirstの取って来ているデータを調べました。

#原因
で、get()ではなくfirst()にするとうまくいったので、
それぞれのwhere直後の$postを見てみると、こんな状態になってました。

##first()で取得した時のデータ
{"id":5,"title":"hoge","body":"hoge"}  

##get()で取得した時のデータ
[{"id":5,"title":"hoge","body":"hoge"}]

#何が違う？
get()の方もfirstの方も、今回「id」でwhere検索しているので、1件しか取得してないのですが
getの方は[]で囲われています。
例えば
[
{"id":9,"title":"hoge","body":"hoge"},
{"id":1o,"title":"fuge","body":"fuge"},
]
のように数件取得して、foreachで一件ずつに「->title」で呼び出すなら問題ない、
複数件前提のデータということになります。

今回のように1件だけ決めうちで取りたいならfirst()を使うべきでした。
こうするとうまく動きました！

```php
   $post = Post::where('id',$id)->first();

```
ApplicationExceptionとは

# 初めに

上司「Qiita(社内で)公開しませんか？」

# ApplicationExceptionとは

しません。

勉強会で__ApplicationException__なるものを知りました。
Exceptionクラスの派生クラスですが、参考書も[MSDN](https://docs.microsoft.com/ja-jp/dotnet/api/system.applicationexception?redirectedfrom=MSDN&view=net-5.0)も「__非推奨__」としています。以下公式より。

> System.ApplicationException をスローしたり、System.ApplicationException から派生したりしないでください。

# 何故非推奨？

結論から言うと、__MicrosoftがExceptionのルールを破ったから__らしいです。

# その昔
- 共通言語ランタイム(CLR)がスローする例外→SystemExceptionクラスから派生
- アプリケーションがスローする例外→ApplicationExceptionクラスから派生

というルールをMicrosoftが推奨していました。
しかし、ある日Microsoftの開発者がそのルールを守らず、CLRがスローするのにApplicationExceptionから派生させてたり、その逆、アプリケーションがスローするのにSystemExceptionから派生させてたりしてしまったとかなんとか...。

当然設計者も使用者も混乱するので、ある日を境に
「全ての例外はExceptionから派生させよう」
とルールを一新し、混乱の元であるSystemApplicationの使用を非推奨としているわけです。

# 最後に

天下のMicrosoft社の人でも間違えるんですね...。非推奨の理由を知って少し驚いたので、まとめさせていただきました。
もし説明に間違いや御幣がある場合は、教えていただければ幸いです。では。
AWS Amplifyのenvを別々のAWSアカウントに構築する

Amplifyでは、同じAWSアカウント内にenvを複数作成することができます。しかし、例えば開発環境と本番環境で別々のAWSアカウントを使いたいという場合もあるかと思います。この記事では、AWS AmplifyのenvをAWSの別アカウントに構築する手順をご説明します。

## 使用したいプロファイルを~/.awsに追加する

~/.aws/config, credentialsにAWSアカウントの情報をプロファイルとして追加しておきます。

## amplify init

`amplify env add`はせず、`amplify init`を実行します。

`? Do you want to use an existing environment?`は No、
`? Enter a name for the environment`はenv名
`Please choose the profile you want to use`に使用したいプロファイル

とすれば、指定したプロファイルのAWSアカウントがデプロイ先になります。dev環境が既に存在していて、prod環境を新たに構築したかったため、env名はprodとしました。

```
% amplify init
Note: It is recommended to run this command from the root of your app directory
? Do you want to use an existing environment? No
? Enter a name for the environment prod
Using default provider  awscloudformation

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

? Do you want to use an AWS profile? Yes
? Please choose the profile you want to use profile-hoge
Adding backend environment prod to AWS Amplify Console app: 
⠴ Initializing project in the cloud...
```

## 構築結果確認

devとprodのAWSアカウントを分離して構築できました。

```
% amplify env list

| Environments |
| ------------ |
| dev          |
| *prod        |
```
初期値よりも最適化アルゴリズムの方が重要だ

何かものごとをいい方向に持っていこうと思うと、誰でも思いつくことは、まず良い状態に持っていこうとすることだ。
でもそれ以上に大事なことが、いい方向に動かしていくための最適化アルゴリズムだ。

## 数値計算問題
数値計算の問題としては、初期値よりも最適化アルゴリズムの方が重要なのは自明だろう。
よい最適化アルゴリズムは、初期値依存性を持たない。
初期値は収束までの時間には影響するけれども、最適な状況にたどり着ける。

## チーム運営
チームの運営のしかたについてのルールをチームで作っていくときにも、同様のことが言える。
チーム運営のついての開始時点での個別のルール（いわば初期値）よりも、チーム運営のルールをどう変えていくかの部分（いわば最適化アルゴリズム）の方が重要だ。
チームの抱えている課題の状況は、開発のフェーズごとに変わっていく。常にこのルールでやれば上手くいく万能のルールがあるとは考えにくい。そうしたら、チーム運営のルールを必要なタイミングに変えていけるやり方の方が重要になってくる。
ソースコードをマージするまでのルール。
ソースコードのテストのしかたについてのルール。
コーディングスタイルについてのルール。
そういったのもあるだろうし、
開発の優先順序の設定についてのルール。
開発チーム内での開発リソースの割当についてのルールもあるだろう。

そういったものが、組織の中で必要なタイミングで変わっていけることこそが大事だ。

## 事業分野の選択と事業戦略
この文章を読んできて気づいたろう。

初期値よりも、最適化アルゴリズムの方が重要なのは、事業分野の選択と事業戦略でも同じだということに。

むかしの経営者は、「集中と選択」と称して事業分野の選択をすることこそが、トップの経営者のすることだと考えていたようだ。
しかし、今後の成長が期待できる事業分野を選択したからといって、それだけでその事業分野で成功できるほど世の中は甘くない。
事業分野の選択は、「初期値」を設定したにすぎないからだ。
その事業分野で成功するためには、成功する状態に向けて自分たちを変えていく力こそが必要だ。つまり、その事業分野で成功するための組織の変え方についての「最適化アルゴリズム」こそが必要なものなのだ。
事業分野ごとに、その事業で成功するために必要なものは変わってくる。
事業分野の開発項目ごとに成功するために必要なものは変わってくる。
事業分野の生産ラインごとに成功するために必要なものは変わってくる。
事業分野の営業ごとに成功するのに必要なものは変わってくる。
事業分野ごとの成功するためには何が必要でどう変わっていけるかが重要だとわかっていれば、遅い・速いの違いはあっても、より望ましい状況に変貌させていくことができるはずだ。

## 事業の組織運営の「最適化」に失敗する要因
- あまりに長すぎる時定数。
    - 年度のはじめに立てた計画は、計画の修正をせずにやりとげようとしてしまうこと。
    
- 過度の分業
    - 事業を成功させるという共通の目標ではなく、◯◯部、△△部の目標に落とし込んだ時点で、事業を成功させるという共通の目標を忘れ去ってしまう。
    - 部門間で情報を分かち合おうとしない。
    - 有能な人物を囲い込んでしまって、その人に有益な情報を伝えない。
- 個人的な利害の優先
    - 組織全体が成功することよりも、その部署の管理者の個人的な損得勘定を優先する。

- トップの言葉に対して言葉尻であっていることを重視し、自分の頭で考えない。
    - トップの人がいう表現は比喩的な表現かもしれない。
    - トップの人がいう表現は、現場を知らないから思い込みで言ってしまった間違いかもしれない。
    - にもかかわらず、トップの人がそういう表現をしたからといって、自分の頭で考えないまま行動する。
 

こういった事業運営のルールを変えていく部分（いわば事業運営の「最適化アルゴリズム」）こそが、事業の成否に影響を与えるものだと、私は思う。

## 最適化アルゴリズムがうまくいっていれば
- どの事業分野を積極的に推進する分野と選んでも、それなりの結果を出せるように変わっていくだろう。
- 事業を成功させる上で必要な人材が不足していたら、そういった人材を引き抜いてくることはできる。
- だれがその分野について適切な判断をできるのかについて、冷静に見極めて、その人の判断を聞くことができる。
Figamaで可変のボックスを作る方法

WEB制作をしていると、ボタンデザインの使い回しをすることが多々あります。
こんな感じに中の文字数だけが異なるパターンですね。
![640ccd4cee96b9b8f1d1950c44ea7b23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/72beb76c-280f-cc50-2cc0-e556143163df.png)

これをFigmaで簡単に作る方法についてご紹介します。

#目指す形
こんな感じで文字数に合わせてボタンのサイズが変わります。
しかも、文字を入力後でも上下左右の余白(padding)を変更することができちゃいます。
![2955c526105ed96edd508ba0aa41d909.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/d12ca10d-d5a7-3780-7f95-7f3861fdfd0d.gif)

#STEP1 要素の作成
ボタンと文字を準備します。
![1d14e0df8ab190f3432a0d88a5f97abb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/0bf84666-c499-3f06-1e83-298ba2c8b928.png)

#STEP2 Add Auto Layoutをする
ここで文字とボタンを選択して、右クリックします。
赤色で囲ってある、`Add Auto Layout`を選択します。
![cf9e117d6e5e5b20f3e7aca1c7f385cc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/db9e46b6-7751-b112-906c-2c0f1645bb43.png)

#STEP3 完成
これで文字数に合わせて可変するボタンの出来上がりです。
上下左右の余白は右側にあるパネルから編集が可能です。

![c6489018c2aacb671bb6e81f4a5a1681.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/693c7de3-9b56-8a49-ceeb-f88de47093d9.png)
JavaScript 非破壊的に要素を追加した配列を生成する

#結論
`push()`を使わず、スプレッド構文を使って新たな配列を生成する。
#サンプル
```JavaScript:sample.js
let students = [['sato'], ['suzuki'], ['takahashi'], ['tanaka'], ['ito']];
//配列の各要素にインデックスの値を追加したい。e.g. ['sato'] -> ['sato', 0]
```

##`push()`

```JavaScript:push.js
let addIndex = students.map(function(el, idx) {
 el.push(idx);
 return el;
});
console.log(addIndex); // [['sato', 0], ['suzuki', 1], ['takahashi', 2], ['tanaka', 3], ['ito', 4]] 

// 元の配列も変更されてしまう。
console.log(students); // [['sato', 0], ['suzuki', 1], ['takahashi', 2], ['tanaka', 3], ['ito', 4]]
```

##スプレッド構文
```JavaScript:spread.js
let addIndex = students.map((el, idx) => [...el, idx]);
//インデックスが追加されている。
console.log(addIndex); // [['sato', 0], ['suzuki', 1], ['takahashi', 2], ['tanaka', 3], ['ito', 4]] 

// 元の配列はそのまま。
console.log(students); // [['sato'], ['suzuki'], ['takahashi'], ['tanaka'], ['ito']];
```

本記事の内容は[別記事](https://qiita.com/lrururu/items/b2418da1325d94d37889)にて@shiracamusさんにご教授頂きました！
ありがとうございました！
表示件数を1ページ目だけ変えるページネーションの実装

#はじめに
表示件数が1ページ目だけ異なるページネーションの実装をまとめました。
紹介した内容以外でもっと良い方法がありましたら教えてもらえると助かります！

#解説
１ページ目に３件、2ページ目以降は10件ずつ表示する場合で解説していきます。
（件数は適当なので、各自好きな数字で調整してみて下さい）

##ページの取得件数を設定

```
$post_per_page = $paged > 1 ? 10 : 3;
```
ページの取得件数を設定しています。1ページ目なら**3**、2ページ目以降なら**10**を設定します。
SQLの`LIMIT句`に`$post_per_page`を設定すれば、テーブルから取得するデータ件数を指定できます。

## 取得するデータの開始位置を設定

```
if ( $paged > 1 )
    $add_args['offset'] = 3 + ( $paged - 2 ) * 10;
```
2ページ目以降は1ページ目の3件＋1ページごとに10件読み飛ばします。
例：2ページ目は4件目から、3ページ目は14件目からデータを取得

ここでの`$add_args['offset']`は`OFFSET句`に指定することで、テーブル上でどの位置からデータを主とするのかを指定できます。

## 合計ページ数を計算

```
$comment_count = 20    //コメント総数
$max_page = ceil(($comment_count - 3) /  10) + 1
```
まず、表示件数の異なる1ページ目をコメント総数から引きます。
引いた結果、2ページ目以降で合計何ページあるか産出されます。
そして、最後に1ページ目を足しています。

#参考
[[WordPress] 1ページ目だけ表示件数が異なるページネーションの実装](http://www.560designs.com/memo/1296.html)
[取得するデータの数と開始位置を指定(LIMIT句, OFFSET句)](https://www.dbonline.jp/sqlite/select/index10.html)
Ubuntu20.04で最新のSamba4をビルド



## 準備

```sh
$ sudo apt update
$ sudo apt upgrade
```

## 最新Sambaダウンロード

```sh
$ curl -LO https://download.samba.org/pub/samba/samba-latest.tar.gz
$ tar xzvf samba-latest.tar.gz
$ cd samba-x.y.z/    # x.y.zはSambaバージョン
```

## 依存ライブラリインストール

参考: https://wiki.samba.org/index.php/Package_Dependencies_Required_to_Build_Samba#Debian_.2F_Ubuntu

```sh
$ sudo apt-get install acl attr autoconf bind9utils bison build-essential \
  debhelper dnsutils docbook-xml docbook-xsl flex gdb libjansson-dev krb5-user \
  libacl1-dev libaio-dev libarchive-dev libattr1-dev libblkid-dev libbsd-dev \
  libcap-dev libcups2-dev libgnutls28-dev libgpgme-dev libjson-perl \
  libldap2-dev libncurses5-dev libpam0g-dev libparse-yapp-perl \
  libpopt-dev libreadline-dev nettle-dev perl perl-modules pkg-config \
  python-all-dev python-crypto python3-dbg python-dev python-dnspython \
  python3-dnspython python3-gpg python-markdown python3-markdown \
  python3-dev xsltproc zlib1g-dev liblmdb-dev lmdb-utils libdbus-1-dev
```

## make install

```sh
$ ./configure --sysconfdir=/etc/samba/  
$ make -j 2
$ sudo make install
$ sudo cp ./examples/smb.conf.default /etc/samba/smb.conf
```

## パスを通す

```sh
$ sudo su -
# echo "PATH=/usr/local/samba/bin:/usr/local/samba/sbin:\$PATH" > /etc/profile.d/samba4.sh
```
気象業務支援センターから防災情報を受け取りサービス化した件

気象庁が発表する気象情報や地震情報は今やどこのサイトでも見られますが、生データが欲しい！というごく一部のマニアックな方々（私）には喉から手が出るほどリアルタイムで情報が欲しい（でもお金はそこまで出したくない）という人がいます。

えぇ、かなりニッチです。


# FTPでリアルタイム？

## まずもって
気象庁の発表する情報はすべて気象業務支援センターを通じ、民間の情報配信サイトや気象会社、各電話会社・テレビ局を通じて気象警報や地震情報が広く発表しています。

その気象業務支援センターで気象庁の配信業務を代行しているのですが、配信形態はいろいろありますが電文で配信されるものに限定すると以下の通りです。

* NTT Communicationsが提供するArcstar Universal Oneを利用したTCP Socket
* FTP-PUT
* SFTP-PUT

による配信があります。
※東京と大阪から同じ電文が1通づつ受け取れます。

そのArcstar Universal Oneですが、法人向けのため一般個人が契約できる代物ではありません。

個人で契約できるのはインターネットを用いたFTP-PUTまたはSFTP-PUTのみとなっています。

今回はFTP-PUTを利用した受信をしてみました。

## リアルタイムだったか
結論から言うと、[気象業務支援センターが定める配信区分](http://www.jmbsc.or.jp/jp/online/denbun/D_datalist.pdf)、そのうちの地震・火山・津波と、注意報・警報については気象庁の発表からおおむね5秒以内に到達します。

地震情報ですとNHKよりちょっと早いぐらいで来ます。

# 受信してサービスにしてみた

気象防災情報配信サービス (DM-D.S.S)
https://dmdata.jp/

今年の4月あたりから正式にサービスを開始したものです。

生データがWebSocketで受け取れたり、PULLで受け取れたり出来ます。

サービス名はちと思いつかなかったので味気ないですが、ご容赦ください。

# 費用
月々大体5～6万円ほどかかっています。
その大半は気象業務支援センターへの費用ですね、41,360円(税込み)がかかっています。

実費のみとはいえ、かなり大きい出費です。
個人でこれを受信しようとするとかなりの覚悟が必要ですね←。

# サービス構築して思ったこと
まず詰みかけたのは決済手段に使おうとしたクレジットカードAPI、[PAY.JP](https://pay.jp/)ですが、個人事業主の開業届が必要でした。
そこから速攻で書類を出し控えをPay.jpに提出して無事審査通りましたが、何分初めてなので手間取りました。

そして次が利用者が全くと言っていいほど増えない。
宣伝が下手なせいですね、これは今後の課題となりそうです。

# いくら利益が出たか
はっきり言ってマイナスうん十万です、安易にやるもんじゃない。

# 最後に
あまりこういうものは書かないのですが、どうだったでしょうか。
これが何かの役に立てばよろしいのですが・・・

最後までありがとうございました。
Realm Databaseのバックアップとリストア

# Realm Databaseのバックアップとリストア
あまりRealmのバックアップとリストアについての記事が見つからないので投稿します。

### 環境
|環境|バージョン|
|---|---|
|Xcode|12.0|
|Swift|5|
|MacOS|Big Sur(11.0.1)|

### Libraryディレクトリ直下にバックアップ
`defaults.realm_bk_yyyy-MM-dd-hh-mm-ss`というファイル名で
現在のdefaults.realm（Realm Database本体）をバックアップします。

```swift:Hoge.swift

    private func hoge() {
        do {
            let url = try FileManager.default.url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            let dateformater = DateFormatter()
            dateformater.dateFormat = "yyyy-MM-dd-hh-mm-ss"
            dateformater.locale = Locale(identifier: "ja_JP")
            let fileName = "default.realm_bk_" + dateformater.string(from: Date())
            try backupLocalStore(storeBackupDirectoryURL: url, backupStoreFilename: fileName)
        } catch {
            print(error.localizedDescription)
        }
    }


    /// Realmを指定の場所にバックアップします。
    /// - Parameters:
    ///   - storeBackupDirectoryURL: バックアップするディレクトリを指定
    ///   - backupStoreFilename: バックアップするファイル名を指定
    /// - Throws: エラー
    private func backupLocalStore(storeBackupDirectoryURL: URL, backupStoreFilename: String) throws {
        let backupURL = storeBackupDirectoryURL.appendingPathComponent(backupStoreFilename)
        do {
            let realm = try Realm()
            realm.beginWrite()
            try realm.writeCopy(toFile: backupURL)
            realm.cancelWrite()
        } catch {
            throw error
        }
    }
```

Library直下にバックアップが作成されています。
![スクリーンショット 2020-11-16 22.49.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88925/4629c513-b594-d76a-bea7-03e625ed80ec.png)

### バックアップしたファイルをリストアする

```swift:Hoge.swift

    private func hoge() {
        do {
            var url = try FileManager.default.url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            url.appendPathComponent("default.realm_bk_2020-11-16-10-46-35")
            try realmRestore(backupFileURL: url)
        } catch {
            print(error.localizedDescription)
        }
    }

    /// Realmをリストアする
    /// - Parameter backupFileURL: バックアップファイル
    /// - Throws: エラー
    private func realmRestore(backupFileURL: URL) throws {
        guard let realmFileUrl = Realm.Configuration.defaultConfiguration.fileURL else {
            throw NSError.init(domain: "Realmのファイルパスが取得できませんでした。", code: -1, userInfo: nil)
        }
        try FileManager.default.removeItem(at: realmFileUrl)
        try FileManager.default.copyItem(at: backupFileURL, to: realmFileUrl)
    }
```

指定したバックアップファイルでデータベースが復元されているのが確認できるはずです。

###懸念事項
今回書いたサンプルコードはRealmが他でアクセスされている事を考慮できていない可能性があります。（特にリストアする時）
ただ、個人アプリ等で絶対にここではアクセスしていないと分かる場面等では利用できるかと思いますので自己責任でご利用ください😇
なにかあればご質問、ご指摘お待ちしております！
バッチファイルの記述メモ

#はじめに
先日、業務でバッチファイルを作成した。今まで実行することばかりだったため興味はあったが、作成してみてすこぶる手こずってしまった。。
中でも独特だった記述についてメモ書き程度に記しておく。

##forコマンド
forコマンド内での変数の扱い方に一癖あり。
バッチファイルのforコマンド内では変数の中身を都度更新してくれない。そのため以下の書き方ではエラーとなる。

```batch:command.bat 
@echo off
rem ファイル内のデータを取得
for /f %%i in (test.txt) do (
    set x=%%i
rem 実行結果でエラー発生
    echo %x%　
)
```

遅延環境変数なるものを使い、以下のような書き方で変数を扱うことで都度取得した情報が変数から参照できるようになる。

```batch:command.bat 
@echo off
rem 遅延環境変数の使用を宣言
setlocal enabledelayedexpansion
rem ファイル内のデータを取得
for /f %%i in (test.txt) do (
    set x=%%i
rem !で変数を囲むことで一行ずつ取得できる
    echo !x!
)
```

####トークンオプションの指定
今回は以下のトークンオプションを使用した。

tokens：何番目のトークンを指定するか
delims：トークンの区切り文字を指定

tokensは指定した個数分、宣言した変数のアルファベット順に値が格納される。

```text:test.txt
1,2,3,4
a,b,c,d
A,B,C,D
```

```batch:command.bat 
@echo off
setlocal enabledelayedexpansion
rem ファイル内のデータを一行ずつ取得
rem カンマ区切りで1,2,3番目のデータを取得
for /f "tokens=1,2,3 delims=," %%a in (test.txt) do (
   rem アルファベット順に格納される
   set x=%%a
   set y=%%b
   set z=%%c
   echo !x!
   echo !y!
   echo !z!
)
```

上記のオプション、トークン以外にも存在するため、ケースに合わせて指定を変える。詳細は以下の記事を参照した。
https://qiita.com/plcherrim/items/67be34bab1fdf3fb87f9

##文字列検索


```batch:command.bat
@echo off
rem 検索対象文字列
set str=abcdefg
rem 検索文字
set search=abc

rem 文字列の検索
echo "%str%" | find "%search%" > NUL
rem 検索結果確認（存在する:0, 存在しない:1）
if not %ERRORLEVEL% 0 (
   echo 存在しました。
)
```

復習がてら、先ほどのforコマンドの中で扱うと以下のようになる。

```batch:command.bat
@echo off
rem 検索文字
set search=abc

rem 区切り文字を空にすることでファイル内のデータを一行ずつ取得
for /f "delims=" %%i in (test.txt) do (
   set str=%%i
   rem 文字列の検索
　　echo "!str!" | find "%search%" > NUL
   if not !ERRORLEVEL! 0 (
      echo 存在しました。
   )
)
```
aws_subnetをmapで作る

# なぜ作った

[前回作ったリスト](https://qiita.com/mochizukithr/items/47c52085188c2ffd78d7)だとoutputで情報を受け取るとき不便だった。

# コード

```hcl:main.tf
module mo_subnet {
  source = "./modules/subnet"

  vpc_id = module.mo_vpc.id

  subnets = {
    namae1 = {
      name              = "namae"
      cidr_block        = "10.0.1.0/24"
      availability_zone = "ap-northeast-1a"
    }
    namae2 = {
      name              = "namae2"
      cidr_block        = "10.0.2.0/24"
      availability_zone = "ap-northeast-1c"
    }
  }
}

output subnetdata {
  value = module.mo_subnet.subnet.namae2.id
}

output subnetdataall {
  value = module.mo_subnet.subnet
}
```


```hcl:./modules/subnet/main.tf
# ====================
#
# Subnet
#
# ====================



variable "vpc_id" {
  type = string
}

variable "subnets" {
  type = map
}

resource aws_subnet this {

  for_each = var.subnets

  vpc_id = var.vpc_id

  cidr_block        = each.value.cidr_block
  availability_zone = each.value.availability_zone

  tags = {
    Name = each.value.name
  }

}

output "subnet" {
  value = aws_subnet.this
}

```


# 参考

-https://www.hashicorp.com/blog/hashicorp-terraform-0-12-preview-for-and-for-each
- https://github.com/terraform-aws-modules/terraform-aws-vpc/blob/v1.0.0/main.tf
IBM Cloud  :PowerSystems Virtual Server: AIX デフォルト yum 設定


PowerSystems Virtual Server でサービス作成した後に、Cloud 側から提供されているVMイメージに
yum が設定されていることに気づきました。(2020/11時点)

----

AIX 7.2 TL4 SP1 イメージで確認 

```
# oslevel -s
7200-04-01-1939
```

####  yum.conf 確認

```yum.conf
# cat /opt/freeware/etc/yum/yum.conf
[main]
cachedir=/var/cache/yum
keepcache=1
debuglevel=2
logfile=/var/log/yum.log
exactarch=1
obsoletes=1

[AIX_Toolbox]
name=AIX generic repository
baseurl=https://anonymous:anonymous@public.dhe.ibm.com/aix/freeSoftware/aixtoolbox/RPMS/ppc/
enabled=1
gpgcheck=0

[AIX_Toolbox_noarch]
name=AIX noarch repository
baseurl=https://anonymous:anonymous@public.dhe.ibm.com/aix/freeSoftware/aixtoolbox/RPMS/noarch/
enabled=1
gpgcheck=0


[AIX_Toolbox_72]
name=AIX 7.2 specific repository
baseurl=https://anonymous:anonymous@public.dhe.ibm.com/aix/freeSoftware/aixtoolbox/RPMS/ppc-7.2/
enabled=1
gpgcheck=0

```

#### repolist 確認

```repolist
# yum repolist
AIX_Toolbox                                                                                                | 2.6 kB  00:00:00
AIX_Toolbox/primary_db                                                                                     | 1.7 MB  00:00:00
AIX_Toolbox_72                                                                                             | 2.5 kB  00:00:00
AIX_Toolbox_72/primary_db                                                                                  | 128 kB  00:00:00
AIX_Toolbox_noarch                                                                                         | 2.5 kB  00:00:00
AIX_Toolbox_noarch/primary_db                                                                              |  93 kB  00:00:00
repo id                                                  repo name                                                          status
AIX_Toolbox                                              AIX generic repository                                             2,706
AIX_Toolbox_72                                           AIX 7.2 specific repository                                          223
AIX_Toolbox_noarch                                       AIX noarch repository                                                250
repolist: 3,179

```

---

##### proxy サーバー設定方法
・AIX Toolbox に直接アクセスできない場合、proxy サーバー設定が有効。

・参考：Configuring YUM and creating local repositories on IBM AIX
https://developer.ibm.com/technologies/systems/articles/configure-yum-on-aix/


/opt/freeware/etc/yum/yum.conf に下記の行を記載

```
proxy=http://<user>:<passwd>@<proxy server hostname>:<port number>
```

または、CLI で http_proxyをexport する

```
# export http_proxy=http://<user>:<passwd>@<proxy server hostname>:<port number>
```

---

rpm モジュールの導入が容易になりますね。


以上です。
5分でわかる!!Dockerの使い方

<h1>5分でわかる!!Dockerの使い方</h1>

Dockerの解説を5分で行うぞ!!
これを読めば、論文の環境を再現することも出来る!!
細かい話はドキュメントを読んでくれ!!

Dockerの使い方は、以下の通り!!

1.<strong>Dockerfileを書く!!</strong>
2.<strong>Dockerfileを元に、buildコマンドを実行しimageを作成する!!</strong>
3.<strong>runする!!</strong>


たったの3ステップ!!

もう一回書くぞ!!
1.<strong>Dockerfileを書く!!</strong>
2.<strong>Dockerfileを元に、buildコマンドを実行しimageを作成する!!</strong>
3.<strong>runする!!</strong>

dokcerにおけるimageとは、プログラムのようなもの!!
そして、それが動いている状態を<strong>コンテナ</strong>と呼ぶ!!

これは、プログラムとプロセスの関係に似ている!!
他の例えだと、クラスとインスタンスの関係に似ている!!

それじゃあ、各ステップの解説に入るぞ!!

<h2>1.Dockerfileを書く!!</h2>

Dockerfileには、imageに焼き付けたい情報を書くのだ!!
つまり、コンテナが動く段階で備わって欲しいやつを書いていくのだ!!

下に例を示すぞ!!!

```
FROM ubuntu:18.04

RUN apt-get update && apt-get install -y vim
```

Dockerfile内の各行は、
<strong>コマンド空白引数</strong>
で構成されている!!

よく使うコマンドを紹介するぞ!!
たったの２つだ!!

<strong>FROM</strong>と<strong>RUN</strong>
だけ覚えておけば何とかなる!!
まずは慣れることが大事だ!!

<strong>FROM</strong>とは、元となるimageを指定するのだ!!
これを書くことによって、image作成が楽になる!!
例えば、tensorflow環境が欲しいなら、それ用のimageが配布されているのだ!!
分からん人は、クラス継承だと思ったらいいのだ!!

<strong>RUN</strong>とは、Linuxコマンドを実行するためのコマンドなのだ!!
RUN空白Linuxコマンドによって、Linuxコマンドを実行するのだ!!

imageにやきつけたいことをRUNによって、実行するのだ!!

例えば、vimを仮想環境立ち上げ時に備わって欲しいなら、

```
RUN apt-get install -y vim
```
をDockerfile内で書くだけなのだ!!

次にimage作成方法に入っていくよ!!

<h2>2.Dockerfileを元に、buildコマンドを実行しimageを作成する!!</h2>
Dockerfileが出来上がれば、あとはbuildコマンドによって、imageを作成するだけなのだ!!

```
docker build -t image名 Dockerfileへのパス
```

たったのこれだけでimageが出来上がるのだ!!

なんてことはないだろ?

<h3>3.runする!!</h3>

クラスが出来上がれば、インスタンスを作りたくなり、
プログラムが出来上がれば、プロセスとして動かしたくなるもんだ!!

それと同じで、imageが出来上がれば、コンテナを立ち上げたくなるだろ!!

```
docker run -it --rm image名
```

これで、晴れて現ターミナル内でコンテナが動くようになるぞ!!


<h2>終わりに</h2>

dockerが分からなくても、
3ステップが頭に入っていれば、何とかなるのだ!!
rvizでメニューバーが表示されない

同じく悩む人がいそうなので記録しておく。


rvizでsave configしようとしたときに、下図のように「File「Panels」「Help」のメニューバーが表示されていないときは
![Screenshot from 2020-11-16 22-50-47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149593/4abab440-6c3e-a986-7b3e-93662a6e5a57.png)

rvizのウィンドウを開いたまま画面の左上端にマウスカーソルを合わせると出てくる。
![Screenshot from 2020-11-16 22-50-39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149593/2bfffe09-d58f-4f8e-13a1-53af6221c6fe.png)
MacOS Big SurにしたらVritualBoxとVagrantが動かなくなったので動かすまでやったこと！

# やったことについて！(すごく簡単)
 - Vagrantのバージョンを最新のものにする(https://www.vagrantup.com/)
 - VirtualBoxのバージョンを最新のものにする(https://www.virtualbox.org/)
 - システム環境設定→セキュリティとプライバシー(一般)→ダウンロードしたアプリケーション(VirtualBox)の実行を許可
 - 再起動する
 - 完了！

あとはいつも通りVagrantfileがある場所で`vagrant up (マシン名)`で起動できました！

## 補足
VMwareを使ってWindowsOSを入れていたのですがそれで使っていたprivate IPアドレスがなぜか繋がらなくなっている！(別の原因かもしれないので調査中！)
Alibaba Cloud Short Message Service(SMS)を調べてみた

2020/11/16現在の情報です。

# Short Message Service(以下、SMS)とは
Alibaba Cloud Short Message Service(SMS)は、OTP(One-Time-Password)、トランザクション通知、プッシュ通知、プロモーションキャンペーンをサポートし、国内外にショートメッセージを送信できるサービスです。

# カバー範囲
SMSは200以上の国と地域をカバーしています。
詳細は[こちら](https://www.alibabacloud.com/help/ja/doc-detail/73693.htm)
国や地域は、アルファベット2文字ないし3文字で表される**Country ISO**と数字で表される**Country(Area) Code**で判別します。
電話番号の前にCountry(Area) Codeを付けて、APIのパラメーターとして設定する際などに利用する事が多いと思います。

# 料金
料金体系は、大きく分けて2パターンあります。
価格表は[こちら](https://www.alibabacloud.com/ja/product/short-message-service/pricing)

* グローバルSMSパッケージ
* ローカルSMSパッケージ

どちらのパッケージも、有効期間は180日です。

## グローバルSMSパッケージ
グローバルSMSパッケージ版は、SMSを世界中(中国本土を含む)に送信できるようです。

## ローカルSMSパッケージ
SMSの送信地域が特定のエリアの場合は、ローカルSMSパッケージの方が単価が安くなります。
現在ローカルSMSパッケージが対応している国または地域は、

* 中国
* インド
* インドネシア
* シンガポール
* 香港
* オーストラリア
* 台湾
* ドイツ
* 戴
* フィリピン
* マレーシア
* マカオ

です。
残念ながら、現時点で日本は含まれていないようです。

# 開発環境
SMSにはAPIとSDKが用意されています。
APIのドキュメントは[こちら](https://www.alibabacloud.com/help/ja/doc-detail/164724.htm)
SDKのドキュメントは[こちら](https://www.alibabacloud.com/help/ja/doc-detail/164735.htm)

## APIについて
ドキュメントにはパラメーターの内容やレスポンスの形式(XMLまたはJSON)が記載されているので分かりやすいと思います。

## SDKについて
SDKはデモが準備されています。
Alibaba Cloudのサービスの一つである、OpenAPI Explorerを利用して分かりやすく動作を確認することができます。
ただし、**AccessKeyID**や**AccessSecret**の情報を入力する必要性があるため、実際にSMSのリソースを作成する必要があり料金が発生するので注意が必要です。

SDKの対応言語は、

* Java
* Node.js
* Go
* PHP
* Python
* .NET
* Ruby

です。
対応しているバージョンは各言語のSDKでご確認ください。
Alibaba CloudのSDKは[GitHub](https://github.com/aliyun)で公開されています。

# まとめ
中国本土向けのSMSは署名(会社やアプリの情報入力)が必要となっていますが、他のエリア向けでは比較的簡単にSMSが送信出来そうだと感じました。
また、OpenAPI Explorerでデモを動かせるので、ドキュメント読みつつ動作を理解しやすい環境が整っているのは便利だと思います。
エラーメッセージの重複をなくしたい

##エラーメッセージの重複①
form_withメソッドを使って、
form.number_fieldで数値を入力させるフォームを作った。
正しい数値を入力すればエラーは起きないし、バリデーションを超える数値を入力しようとすると、そのタイミングでエラーが出る。
しかし、空のまま入力フォームを送ると、

---
○○を入力してください
○○は不正な値です
○○は一覧にありません

---

と、エラーが３つも出てしまう。
空を送信しただけで、３つもいらん！！！

###解決方法

```ruby:model
with_options presence: true do
    validates :grade, format: { with: /\A[0-9]+\z/, allow_blank: true}, inclusion: { in: 1..7, allow_blank: true }
    validates :class_number, format: { with: /\A[0-9]+\z/, allow_blank: true }, inclusion: { in: 1..10, allow_blank: true }
end
```

formatは正規表現のバリデーション。
inclusionは数値の範囲のバリデーション。

`allow_blank: true`は値が空の場合はバリデーションを実行しないメソッド。
冗長だが、これで空のときにはformatとinclusionのバリデーションは反応しない。

改めてエラーメッセージを見ると、
「○○は不正な値です」はformatに反応していて、
「○○は一覧にありません」はinclusionに反応していることがわかる。



##エラーメッセージの重複②
外部キーを使っている状態で、そこに`presence: true`のバリデーションをかけると、同じような内容で2つのエラーメッセージが出る。

###解決方法
モデルに記述している、外部キーのバリデーションを消す。

##【余談】エラーメッセージの順番を変えたい

順番はバリデーションとアソシエーションの記述位置を変える事で解消できる。記述の位置を変えるだけなので、特段問題が起こらないことが有難い。
これは、コードが上から読み込まれていることに起因すると考えられる。ちょっとしたことだけど、入力フォームの順に、エラーメッセージを出してあげたい。
Goで香水を実装してみる

# はじめに

この記事は，学校の帰りに思いついたものを勢いだけで実装したクソコードを載せているだけのネタ記事です．
間違ってもこれを見てGoの勉強をしようなどと思わないでください．

若干 「[Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2)」にインスパイアされている部分があります．

# 実装する
## コード

```main.go
package main

import (
	"fmt"
)

type human struct {
	Dolce   bool
	Gabbana bool
	Kousui  perfume
}

type perfume struct {
}

func (p *perfume) say() {
	fmt.Println(`僕がフラれるんだ`)
}

func main() {

	Kimi := human{true, true, perfume{}}

	if Kimi.Dolce && Kimi.Gabbana {
		Kimi.Kousui.say()
	}
}
```

これが実際のコードです．fmtパッケージしか使っていないので，基本的な環境構築ができていればこのままコピペで動くはずです．
今回実装したのは，曲の中で最も有名であろう，「君のドルチェ&ガッバーナの その香水のせいだよ」の部分になります．実装するにあたって，歌詞を調べてみると他にも実装したら面白そうな部分があったので，暇なときにでも完全版を作りたいです(適当)

## 解説
### 構造体

```
type human struct {
	Dolce   bool
	Gabbana bool
	Kousui  perfume
}

type perfume struct {
}
```

今回，使用した構造体は

- human
- perfume

の２つです．
`human`は歌詞中の「君」を表現するために使用しました．
`perfume`は名前の通り「香水」の部分です．この機能なら構造体にする必要もなかったのですが，次項で解説するメソッドを使用したかったため構造体にしています．

### 条件式

```
	if Kimi.Dolce && Kimi.Gabbana {
		Kimi.Kousui.say()
	}
```

**ここが一番実装したかった部分です.**

`perfume`を構造体にして，sayメソッドを追加しているので，「KimiのDolce && Gabbanaの そのKousuiのsayだよ」というように実装できます．


## おまけ

このコードでは，Dolce と Gabbanaの値が一定のため，何度実行しても同じことの繰り返しでまたフラれてしまいます．
そこで，

```
package main

import (
	"fmt"
	"math/rand"
)

type human struct {
	Dolce   bool
	Gabbana bool
	Kousui  perfume
}

type perfume struct {
}

func (p *perfume) say() {
	fmt.Println(`僕がフラれるんだ`)
}

func main() {

	Kimi := human{true, true, perfume{}}

	if rand.Intn(2) == 0 {
		Kimi.Dolce = false
	}

	if rand.Intn(2) == 0 {
		Kimi.Gabbana = false
	}

	if Kimi.Dolce && Kimi.Gabbana {
		Kimi.Kousui.say()
	}
}

```

というように`rand.Intn(2)`を追加して25%の確率で香水のせいにするように変更してみました．

# あとがき

こんな雑な記事をここまで読んでいただき，ありがとうございました．
今回はGoで香水(Go水)を実装しましたが，Pythonで書けば`if Dolce and Gabbana`って書けるなーなどと思ったので，他の言語でも実装してみると面白いかもしれません.