OmniAICreator/Qiita-1.07M huggingface dataset:
Connpassのイベント概要をTeamsやSlack向けにいい感じにテキスト化するブックマークレット

Connpassのイベント情報を、例えば会社のTeamsとかコミュニティのSlackとかにはろうと思った場合、
ただリンクだけ貼るよりも、日付や開始時刻なども書いてあったほうが親切ですよね。

ということで、その辺の情報もまとめて、SlackやTeamsにコピペすればいいような形に出力するブックマークレットつくりました。

※ブックマークレットって何？どうやって使うの？どうやって作るの？という方は以下を参照ください。

[ブックマークレットを覚えて、決まったブラウザ操作をラクにしていこう - ひびテク](https://yoshikiito.net/blog/archives/1623/)

## コード

``` javascript
javascript: (function () {
  var title = document.t;
  var date = document.getElementsByClassName("ymd")[0].innerText;
  var time = document.getElementsByClassName("hi")[0].innerText;
  c = window.open();
  c.document.open();
  c.document.write(document.title);
  c.document.write("<br>");
  c.document.write('<a href="' + document.URL + '">' + document.URL + '</a>');
  c.document.write("<br>");
  c.document.write("開催日：" + date);
  c.document.write("<br>");
  c.document.write("開始時刻：" + time);
  c.document.close()
})();
```

## 使用結果の例

[QAエンジニアのためのOSSコントリビュートハンズオン - connpass](https://connpass.com/event/165211/)

のページで使うと、以下のようなテキストを別タブに表示します。

``` txt
QAエンジニアのためのOSSコントリビュートハンズオン - connpass
https://connpass.com/event/165211/
開催日：2020/02/17(月)
開始時刻：19:30
```

あとはこのタブ上でCtrl+a, Ctrl+cして全コピーして、お好きな場所に貼り付ければOK。

## 貼り付けた場合のサンプル

### Teams

<img width="525" alt="スクリーンショット 2020-03-13 1.09.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/e86fa859-3ec4-c934-2789-9a4b1181f5e6.png">

### Slack
<img width="653" alt="スクリーンショット 2020-03-13 1.10.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/b9fa3cd9-14b8-dd67-0ed0-de73e1f0f943.png">
『Linuxで動かしながら学ぶTCP/IP入門』でネットワークを実践しながら理解できた（Docker環境つき）

[『Linuxで動かしながら学ぶTCP/IP入門』](https://www.amazon.co.jp/exec/obidos/ASIN/B085BG8CH5/momijiame-22/)がとても勉強になりました。  

「ネットワークの初歩の初歩」ですが、これまでの解説本と異なって実際にpingを飛ばしたりtcpdumpで疎通を覗き見したりしながら学習できます。
そのためようやく「ネットワークとは」とか「TCPとは」とか「NAT(NAPT)の仕組みとは」などを把握することができました。

以下、各章で学んでおきたいことのチェックリストです。
このあたりに不安がある方は、ぜひ読んでみることをおすすめします。

また本書の実践をDocker上で試せるように準備したので、よろしければどうぞ。
https://github.com/koboriakira/tcp_ip_guide

## TCP/IP とは

- [ ]  pingの結果が読めるようになった
- [ ]  tcpdumpでping（icmp）の通信を見れるようになった
- [ ]  端末からルーターを通してインターネットに繋がっているイメージをつかむ

## Network Namespace

- [ ]  `netns` コマンドを利用して、同一セグメント内の仮想のネットワークを作成できる
- [ ]  `netns` コマンドを利用して、ルーターをはさんだネットワークを作成できる
- [ ]  `netns`関連のコマンドをある程度調べずに打てるようになる

## イーサネット

- [ ]  前章の疎通をMACアドレス基準で覗き見できるようになる
- [ ]  ブリッジ（スイッチングハブ）について、Network Namespaceで仮想環境を構築できるようになる
- [ ]  ブリッジの仕組みを理解している

## トランスポート層のプロトコル

- [ ]  アプリケーションとポートの関係を説明できる
- [ ]  UDPとTCPの違いを説明できる

## アプリケーション層のプロトコル

- [ ]  HTTPサーバを立てて疎通させることができる
- [ ]  名前解決について説明できる
- [ ]  IPアドレスが自動的に付与される操作をできる

## NAT

- [ ]  NAT(NAPT)について説明できる
- [ ]  NAT(NAPT)の仕組みを `netns` でつくって試すことができる
LinuxでGithub Desktopを使う

# 入手

ここにappimage,debian,rpm形式で公開されている。

https://github.com/shiftkey/desktop
https://github.com/shiftkey/desktop/releases/tag/release-2.3.1-linux1

リリースノートの下の方にリンクがある↓

![ download_githubdesktop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421175/e122764e-be2d-1e45-a6da-1c05242a1543.png)

# CentOS8に入れようとした

どうもlibappindicatorで怒られてうまくいかない。CentOS7ならいけるのかも

```
nothing provides libappindicator needed by github-desktop-2.3.1_linux1-1.x86_64
```

# 仕方ないので

rpmではなくappimage形式の方を使う

![githubdesktop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421175/24e71d0f-7500-b0b2-77e7-415050f70278.png)

appimage形式については<a href="https://www.virment.com/how-to-use-appimage-linux/">こちら</a>を参考に
wordpressでアドバンスドカスタムフィールドが保存するだけで消える…どうすんだ…（上限があるらしい）

#wordpressの保守作業
## カスタムフィールドの追加
保守案件でカスタムフィールドの追加をするのが来た。
めんどいなーと思いつつ追加。
![q1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104078/fba72920-ddda-5a0c-3ee8-5a92d9fe4e88.png)

ぼちぼちめんどい条件判定入れてる。
これで近畿エリアを追加して、大阪府を追加してーという作業を行った。

動作確認を行って、ちゃんと動いてんなーっていうことを見て就寝。

## 入電
クライアントさんから入電。
またいつもの世間話やろーはなほじーとしてたらLINEが。
> 客先から給料とかの値が表示されてないと連絡がありました。
自分も確認したら表示されてませんでした。
広告を落とされてしまうので支給対応お願いします。

と…
軽く青ざめる。
バックアップ取ってたっけかな…事前にはとってねーな…
折り返しの電話をいれる。

自分：LINE見ました
クライアントさん： あの作業してからですかねー？
自分：多分そうですね。確認してみます。

## ただ追加しただけなのに消えるなんてことあるかーい！
ということでとりあえずワードプレスにログイン。
カスタム投稿の記事を確認する。
「え、フィールド自体無いんだが・・・」
アドバンスドカスタムフィールドを確認する。
「え、すくねえ・・・」
そう。
アドバンスドカスタムフィールドが**20項目位すっぽりと無くなっていた**のだ！！！

だめなやつー
バックアップから復旧しないとだめなやつー
ちゃんとバックアップ取れてるかな…最近確認してないからな…

あ！！！った！！

ということでbackwpupプラグインはちゃんと動いていた模様。
あぶねーｗｗｗ
最新のzipをダウンロードしてきて解凍。
sqlの圧縮ファイルも解凍。

## 復旧作業
conohawingの管理画面からphpmyadminにログイン
![ConoHaコントロールパネル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104078/54b55ea4-f117-d725-5049-a89997fd27bc.png)

phpmyadminのインポートから用意したsqlファイルをアップロード。
復旧完了。
（作業する前に別なテストサイトで一応確認してからやった。だって怖いもん）

## 復旧連絡
**プルルルルプルルルル・・・ガチャ**
**クライアントさん**「はい、○○商事」
**自分**「ああっ、ぼくです！なおりましたーｗｗ
　なんかー普通にカスタムフィールドをー追加しただけなにーきえててーあたいもーよくわかんなくてーごめんねーてへぺろー☆彡」
**クライアントさん**「クレームになることなので確認をしっかりしてください」
**自分**「はーいごめーんね☆彡」

というギリギリの状況だったがなんとか事なきを得た。

## 保守のやり直し
くっそだるい。
またカスタムフィールド追加とかだるい。
と思いつつ追加作業を行う。
追加して保存ボタンをポチー

**ん。。。何かがおかしい。すくねえ。。。**

保存するとカスタムフィールドの数が何回やっても56個になるのである。
こういう時はぐーぐるさん。
「**アドバンスドカスタムフィールド　消える**」
とかで検索。

そしてHitしたのが
https://firegoby.jp/archives/4716

ここだ。

そっかー
**max_input_vars**が関係してくるんだー
conohaってそういうのできんのかなー？
うーんできるっぽーい

ということであんまり上げないように
**max_input_vars = 1500**
に変更。
![ConoHaコントロールパネル1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104078/be851e35-ee75-41fc-4482-b61a8d8c4434.png)

そしてワードプレスのアドバンスドカスタムフィールドの保存ボタンを恐る恐るポチー

！！
保存されている！！！

ということで、アドバンスドカスタムフィールドには**max_input_vars**に依存した上限があるよっていう話でした。
（これ保守でやる作業じゃないでぇ・・・そんなに金もらってねーし・・・今日はもうやんない。だってもう眠いし）
Scala：AkkaHttpでMicrosoft Teamsにメッセージを送信する


# １．はじめに

- Temasアプリからwebhook用のURIを取得します。
    - メッセージを送信したいチャネルで、**「･･･」→コネクタ→Incoming Webhook→構成→作成**　を行い、**表示されたURI（①）**を控えます。

# ２．Scalaプロジェクトを作成

```powershell
sbt new sbt/scala-seed.g8
```

# ３．依存関係の設定

## １）Dependencies.scala 

```project/Dependencies.scala

object Dependencies {
  lazy val akkaActor= "com.typesafe.akka" %% "akka-actor" % "2.6.3"
  lazy val akkaHttp= "com.typesafe.akka" %% "akka-http" % "10.1.11"
  lazy val akkaStream="com.typesafe.akka" %% "akka-stream" % "2.6.3"
}
```

## ２）build.sbt 

```build.sbt
lazy val root = (project in file("."))
  .settings(
    name := "teamsBotSample",
    libraryDependencies ++= Seq(
      akkaActor,
      akkaHttp,
      akkaStream
    ) 
```

# ３．実装
## 1) import

```src/main/scala/Main.scala

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{ Failure, Success }
```

## 2) TeamsBotClientクラス

```src/main/scala/Main.scala

//TeamsBotClientクラス
class TeamsBotClient (uri:String,implicit val system:ActorSystem){
  def request(message:String):Future[HttpResponse]={
    Http().singleRequest(
      HttpRequest(
        method = HttpMethods.POST,
        uri = uri
      ).withEntity(
        HttpEntity(
          ContentTypes.`application/json`,
          s"""{"text":"${message}"}"""
        )
      )
    )
  }
}
```

## 3) Main

```src/main/scala/Main.scala

object Main extends App {

  /* Actorを起動 */
  val system = ActorSystem()

  /* ①で控えたwebhookのURI */
  val uri = "https://outlook.office.com/webhook/~~~~~~~~~~~~~~~~~~~~~~" 

  /* TeamsBotClientインスタンスを作成 */
  val teamsBotClient:TeamsBotClient = new TeamsBotClient(uri,system)

  /* 送信メッセージ */
  val message="はろーわーるど"
 
  /* メッセージを送信 */
  teamsBotClient.request(message).andThen {
      case Success(res) => {
        val httpStatus=res.status.intValue()
        httpStatus match{
          case x if x==200  =>{
            println("%s:request succeeded".format(httpStatus))
          }
          case _ => {
            println("%s:request error".format(httpStatus))
          }
        }
      }
      case Failure(t) => {
        t.printStackTrace()
      }
    }.andThen{
      case _ => system.terminate
    }
}
```

# ４．送信結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204514/2026fc25-2b4b-b901-ba45-c13d186fa4c9.png)


# ５．その他

## powerwhellの場合
- ファイルの文字コードはShiftJIS

```teamsBotTest.ps1
$uri = "https://outlook.office.com/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
$mes="はろー　わーるど"
$body = ConvertTo-JSON @{text = $mes}
$body = [Text.Encoding]::UTF8.GetBytes($body)
Invoke-RestMethod -uri $uri -Method Post -body $body -ContentType 'application/json
```


以上。
Codeforces Round #627 Div.3 A. Yet Another Tetris Problem

https://codeforces.com/contest/1324/problem/A

# 題意
- 横n列にa1, a2,,,anこのブロックが積みあがっている
- あなたか横1 x 縦2のブロックを自由に落とせる
- 横一列(n列)並んだブロックは消える
- すべてのブロックを消せるか調べろ

# こう考えた
まず、すべてが偶数の場合、消せる。0,2,4なら6,6,6にすればよい。
また、すべてが奇数の場合も消せる。1,3,9なら9,9,9にすればよい。
※むろん、上記を積む途中で消えるが

しかし、奇数と偶数が混ざると消せない。
1,2,5は1列消えて0,1,4になる。例えば、4,3,4にしても0,1,0になる。など、どのように消しても残ってしまう。

なので、すべての数が偶数か奇数化を判定すればよい。

# コード
```Python

qq = int(input())
for _ in range(qq):
    n = int(input())
    dat = list(map(int, input().split()))
    if n == 1:
        print("YES")
        continue
    c = dat[0] % 2
    f = True
    for i in range(n):
        if c != dat[i] % 2:
            f = False
    print("YES" if f else "NO")
```
https://codeforces.com/contest/1324/submission/73023892
vimの便利なコマンド


<br>
vimについて学習したので、復習を兼ねてまとめます。

#vimとは
Unix系のエディタ。通常のエディタと違い、いくつかのモードがある。
● ノーマルモード：カーソルの移動やテキストの削除、コピー、ペーストなどの簡単な指示を行う。
● 入力モード：実際にテキストを入力する。(『i』を打つとなり、『ESCキー』を打つと（ノーマルモードに戻る。)
● コマンドモード」：ファイルを開いたり、検索や置換などの様々な指示を行う。(『:』を打つとなり、『ESCキー』を押すとノーマルモードに戻る。)
● ビジュアルモード」：テキストを選択するだけのモード。(『v』を打つとなり、『ESCキー』でノーマルモードに戻る。)



#ファイルの保存、読み込み
| キー       |動作|
|:-----------------|:------------------|
|:q             |終了|
|:w           |保存|
|:wq             |保存して終了| 
|:w 新しいファイル名               |名前をつけて保存| 
|:q!             |変更点を無視して強制的に終了|
|:e 開きたいファイル名          |他のファイルを開く|

#移動
| キー       |動作|
|:-----------------|:------------------|
|gg|ファイル先頭に行く|
|G|ファイル末尾に行く|
|control+f|一画面下に移動|
|control+b|一画面上に移動|
|w|単語単位で移動|
|b|単語単位で戻る|
|^|行頭へ移動|
|$|行末へ移動|


#範囲選択
| キー       |動作|
|:-----------------|:------------------|
|v|文字単位で選択|
|V|行単位で選択|
|control+v|矩形選択|
|gg+V+G|テキスト全体選択|


#カット、コピー、貼り付け
| キー       |動作|
|:-----------------|:------------------|
|x|一文字単位で削除|
|dd|行単位で削除|
|消したい行数の値dd|入力した値の行数分削除|
|p|カットしたものを貼り付ける|
|yy|コピー|

#検索
| キー       |動作|
|:-----------------|:------------------|
|/検索語|検索語のところへ移動|
|(検索語が複数ある場合)n|下方向に検索|
|検索語が複数ある場合)N|上方向に検索|
|*|カーソルがある位置の単語を下方向に検索|
|#|カーソルがある位置の単語を上方向に検索|


#置換
| キー       |動作|
|:-----------------|:------------------|
|:s/元の単語/変更後の単語/|一文字だけ変更(カーソルがある行に有効)|
|:s/元の文字/変更後の文字/g|複数の文字を変更(カーソルがある行に有効)|
|:%s/元の文字/変更後の文字/g|複数の文字を変更(ファイル全体に有効)|
|:%s/元の文字/変更後の文字/gc|複数の文字を変更(ファイル全体に有効)の前に確認コメントが表示される|


#操作の取り消し
| キー       |動作|
|:-----------------|:------------------|
|u|行った操作を取り消す(何度でも戻れる)|
|control+r|uの動作のやり直し|

#ウィンドウの分割
| キー       |動作|
|:-----------------|:------------------|
|:sp|ウィンドウを縦方向に分割|
|:vs|ウィンドウを横方向に分割|
|control+w+w|次のウィンドウに移動|
|control+w+p|前のウィンドウに移動|
|:close|ウィンドウを閉じる|

#タブを使う
| キー       |動作|
|:-----------------|:------------------|
|:tabnew|新しいタブを開く|
|:tabe 開きたいタブ名|指定したタブを開く|
|:gt|タブの移動|
|:tabclose|タブを閉じる|
|(vimを起動時)vim -p|タブを全て開く|
|:tabdo %s/元の単語/変更後の単語/g|開いている全てのタグにおいて置換をする|

#直前の操作を繰り返す
| キー       |動作|
|:-----------------|:------------------|
|.|直前の操作を繰り返す|

#インデント
| キー       |動作|
|:-----------------|:------------------|
|=|カーソルのある行をインデントする|
|全選択後(gg+V+G)=|全ての行をインデントする|

#補完機能
| キー       |動作|
|:-----------------|:------------------|
|control+n|関数をもう一回使う|

#コマンドモードで使える便利な設定
| キー       |動作|
|:-----------------|:------------------|
|:set number|行番号を表示|
|:set nonaumber|行番号を消す|
|:syntax on|コードの色分け|
|:syntax off|色を消す|
|:set tabstop=規定したい文字数|タブの文字数を規定する|
|:set ignorecase|大文字小文字の区別をせずに検索|
|:set noignorecase|元に戻る|
factory_botとcreate_listとテストが通らない素人

## はじめに
　先日、`factory_bot`の`FactoryBot.create_list`メソッドで詰まったので記録しておきます。

　例では`User`モデルと`Post`モデルが１対多で対応していることとします。

## やりたかったこと
　`FactoryBot.create_list`は複数のテストデータを生成する`factory_bot`のメソッドです。それぞれ異なる`Post`を持った`User`オブジェクトを複数作ろうとしました。

```ruby
FactoryBot.create_list(
  :user,
  5,
  post: FactoryBot.create(:post)
)
```

　しかし、生成される`post`はどれも同じもので、想定する挙動ではありませんでした。

## 何がダメだったのか
　どうやら、`create_list`の挙動としてある一つの属性に対してランダムな値を入れることはできないようです。上の例では、`post: FactoryBot.create(:post)`の箇所で同じ`post`が使いまわされているようでした。
　以下のgithubのイシューに私と同じ場面に遭遇した方のコメントがありました。

https://github.com/thoughtbot/factory_bot/issues/787
<img width="1014" alt="スクリーンショット 2020-03-13 0.36.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299664/0c392dee-a028-6fc8-c25f-131f844486ca.png">

## 解決策
　上記のイシューでは、あらかじめ用意しておいた配列に対して`map`を使い、それぞれの要素に対して`FactoryBot.create`するという解決策が提示されていました。`each`でも良さそうですね。以下がコメントにあったコードです。

```ruby
%w(NYC Boston SF Austin).map do |tb_location|
  FactoryBot.create(:location, city: tb_location)
end
```

　余談ですが、そのときの私は`times`を使いました。欲しい挙動にも依りますが、確実に違う値を入れたいというときは上の方が良さそうですね。

```ruby
5.times do
  FactoryBot.create(:user, post: Factory.create(:post))
end
```

## おわり
　`binding.pry`で引っかかる箇所を特定してからも時間がかかってしまいました。こういった細かな挙動を押さえておくのは地道な積み重ねですね。
【PHP】foreachで配列の最初と最後の処理を制御する

# 目的
「`php foreach 最初と最後`」「`php foreach 最後`」「`php foreach last`」などで検索すると、少し微妙な例ばかり出てきたので書いてみました。
なるべくベストパターンを載せるように努めていますが、何かあれば編集リクエストもしくはコメントを送っていただけると助かります。

# PHP 7.3以上の場合

## 実装

```php

$array = ['a', 'b', 'c', 'a']; // 0始まりでない配列や連想配列でもOK
foreach ($array as $index => $value) {
    if ($index === array_key_first($array)) {
        // 最初(始端処理)
        echo 'おはよう!', '<br>';
    }

    echo $value, '<br>';

    if ($index === array_key_last($array)) {
        // 最後(終端処理)
        echo 'おやすみ。', '<br>';
    }
}
```

## 結果

```html

おはよう!
a
b
c
a
おやすみ。
```

# PHP 7.3未満の場合

公式にPolyfillが載っているため、それに従いましょう。
（array_key_lastの方はUser Contributed Noteですが）

> PHP: array_key_first
> https://www.php.net/manual/ja/function.array-key-first.php#refsect1-function.array-key-first-notes

> PHP: array_key_last
> https://www.php.net/manual/ja/function.array-key-last.php#123016

## 実装

```php

// 関数定義
if (!function_exists('array_key_first')) {
    function array_key_first(array $arr) {
        foreach($arr as $key => $unused) {
            return $key;
        }
        return NULL;
    }
}
if (!function_exists("array_key_last")) {
    function array_key_last(array $arr) {
        if (empty($arr)) {
            return NULL;
        }

        return array_keys($arr)[count($arr) - 1];
    }
}

// メイン処理
$array = ['a', 'b', 'c', 'a']; // 0始まりでない配列や連想配列でもOK
foreach ($array as $index => $value) {
    if ($index === array_key_first($array)) {
        // 最初(始端処理)
        echo 'おはよう!', '<br>';
    }

    echo $value, '<br>';

    if ($index === array_key_last($array)) {
        // 最後(終端処理)
        echo 'おやすみ。', '<br>';
    }
}
```

## 結果

```html

おはよう!
a
b
c
a
おやすみ。
```

# アンチパターン集
## reset, endを使うパターン

**バグるので絶対に使ってはいけません。**
reset()は配列の最初の要素を返すため、要素に重複があると複数回実行されてしまいます。
end()も同様です。

### 実装

```php

$array = ['a', 'b', 'c', 'a'];
foreach ($array as $value) {
    if ($value === reset($array)) {
        // 最初(始端処理)
        echo 'おはよう!', '<br>';
    }

    echo $value, '<br>';

    if ($value === end($array)) {
        // 最後(終端処理)
        echo 'おやすみ。', '<br>';
    }
}
```

### 結果

```html

おはよう!
a
おやすみ。
b
c
おはよう!
a
おやすみ。
```

## 現在のインデックスをインクリメントするパターン

最後の判定だけ行うやつです。
インクリメントが冗長だしトレースがだるいのでおすすめしません。

### 実装

```php

$array = ['a', 'b', 'c', 'a'];
$i = 0;
foreach ($array as $value) {

    echo $value, '<br>';
    $i++;

    if ($i === count($array)) {
        // 最後(終端処理)
        echo 'おやすみ。', '<br>';
    }
}
```

### 結果

```html

a
b
c
a
おやすみ。
```

# 動作環境
- PHP 7.4.1
Railsの記法

##記法
link_to
飛ばしたいページを指定できます。

```
<%= link_to "リンク名", "飛ばしたいページ" %>
```
image_tag
画像ファイルを指定できます。

```
<%= image_tag "XXXX.png", alt: "YYYY", id: "ZZZZ", class: "AAAA", width: "XXXpx" %>
```
button_tag
ボタンを作成することができるヘルパーメソッドです。

```
<%= button_to "ボタン名", { パス or コントローラー名,アクション名 }, { オプション } %>
```
パスの指定

```
new_user_session_path  //_pathで指定します
```
Wordpressでプラグインを使わずカスタム投稿タイプを追加する方法

## プラグインを使わず投稿タイプを追加
- functions.phpに以下の関数を追加
- 具体的なオプションについてはcodex参照
[register_post_type()](https://developer.wordpress.org/reference/functions/register_post_type/)
- taxonomyは投稿と同じものを使えるが、分けたほうがいいかも

```php
// functions.php
function create_posttype() {
  register_post_type( 'products',
    // オプション設定
    array(
      'labels' => array(
        'name' => __( '製品一覧' ),
        'singular_name' => __( '製品情報' )
      ),
      'public' => true,
      'has_archive' => true, // 一覧ページを有効化する場合true
      'taxonomies' => array('category','post_tag'),
      'rewrite' => array('slug' => 'products'),
      'show_in_rest' => true,
    )
  );
}
add_action( 'init', 'create_posttype' );
```

## カスタム投稿タイプの表示方法
- 投稿タイプごとに使用するテンプレートを分ける場合は次のようにする
- ループ処理は通常の記事と同じでOK

```php
// 一覧ページ
archive-{post_type}.php
archive-products.php
// 個別記事
single-{post-type}.php
single-products.php
```

## カスタム投稿タイプを表示しようとすると404エラーになる場合の対策
- 新しくカスタム投稿タイプを追加するときは`flush_rewrite_rules();`を追記する
- この関数を使ってリライトルールを更新する必要がある
- 何度かブラウザを更新して記事が表示されたら`flush_rewrite_rules();`を削除する

```php
// 追加した関数の続きに追記
function create_posttype() {
  // 省略
}
add_action( 'init', 'create_posttype' );
// 記事が表示されたら削除するのを忘れずに
flush_rewrite_rules();
```
DB設計論

# サロゲートキーとナチュラルキーとは

Railsからのデファクトはどちらか。
ORMと連携しやすい。仕様変更にも強い。のはどちらか

# 外部キー付ける付けない論

ER図にリレーション貼るだけ
ロジックで処理
PythonでEthereumアカウントを作る

備忘録

```
$ pip install eth-account
```

```create.py
from eth_account import Account

acct = Account.create('RANDOM STRING')
print(acct.address)
# 0x37B654931470E0319583ba097d4fbb79276b1067
print(acct.key)
# b'nq\x9b\x1a\x87\xc6/\xbf\x97\x91/\x1fj\xe2/]S\x87\x8d\x84\x9e\x1b\xb7\x18\xf8\xcfj\xc7A{h\x04'
```

# 参考
https://github.com/ethereum/eth-account
個人アプリ制作

javascriptでブロック崩し制作、投稿アプリをやろうと思ったが、せっかく作るなら自分の作ってみたもの楽しいものと思い制作。
初めてプログラミングをやって楽しい感覚が少し分かった気がする、明らかに今までカリキュラムで制作した投稿アプリとは違いモチベーションが全然違う。
ただ自分の思い通り行くことはない。
操作するバーが上にいき位置が変だったり、ボールが現れない、変な位置で表示、動かない、いろんなエラー、記述ミスがあった。
ミスがあるとこの記述はどういう意味なのか、こういう動きに結びついているのかということを考えながら見ていると、最初は何が書いてあるのかわからないが、だんだんたぶんこれがこうかなと、なんとなくコードが読めていく感覚があった。
コピペでも一から制作するのは勉強になる。まだ超初心者無駄なことは何もない、なんでもやってみる精神大事！！！！

arc　円
Math.PI 円周率
Math.random()　ボールをランダムに動かす
【今日のアブストラクト】Deep Residual Learning for Image Recognition【論文 ほぼ Google 翻訳 自分用】

1 日 1 回 (努力目標) 論文の Abstract を Google 翻訳の力を借りて読んでいきます.

この記事は自分用のメモみたいなものです.
ほぼ Google 翻訳でお送りします.
間違いがあれば指摘していだだけると嬉しいです.

翻訳元
[Deep Residual Learning for Image Recognition](https://arxiv.org/abs/1512.03385v1)


# Abstract

### 訳文
より深いニューラルネットワークは, トレーニングがより困難です. 以前に使用されていたものよりもかなり深いネットワークのトレーニングを容易にするための残差学習フレームワークを提示します. 参照されない関数を学習する代わりに, レイヤー入力を参照して残差関数を学習するようにレイヤーを明示的に再定式化します. これらの残差ネットワークは最適化が容易であり, 深さが大幅に増加することで精度が向上することを示す包括的な経験的証拠を提供します. ImageNet データセットでは, 最大 152 層の深さの残差ネットを評価します. これは, VGG ネットの 8 倍の深さですが, 複雑さは低くなっています. これらの残差ネットのアンサンブルは, ImageNet テストセットで 3.57% のエラーを達成します. この結果は, ILSVRC 2015 分類タスクで 1 位になりました. また, 100 および 1000 層の CIFAR-10 の分析も示します.
表現の深さは, 多くの視覚認識タスクにとって最も重要です. 表現が非常に深いため, COCO オブジェクト検出データセットで 28% の相対的な改善が得られています. Deep residual nets は, ILSVRC & COCO 2015 コンテストへの我々の提出の基礎であり, ImageNet 検出, ImageNet ローカリゼーション, COCO 検出, および COCO セグメンテーションのタスクで 1 位を獲得しました.

### 原文
Deeper neural networks are more difficult to train. We present a residual learning framework to ease the training of networks that are substantially deeper than those used previously. We explicitly reformulate the layers as learning residual functions with reference to the layer inputs, instead of learning unreferenced functions. We provide comprehensive empirical evidence showing that these residual networks are easier to optimize, and can gain accuracy from considerably increased depth. On the ImageNet dataset we evaluate residual nets with a depth of up to 152 layers---8x deeper than VGG nets but still having lower complexity. An ensemble of these residual nets achieves 3.57% error on the ImageNet test set. This result won the 1st place on the ILSVRC 2015 classification task. We also present analysis on CIFAR-10 with 100 and 1000 layers.
The depth of representations is of central importance for many visual recognition tasks. Solely due to our extremely deep representations, we obtain a 28% relative improvement on the COCO object detection dataset. Deep residual nets are foundations of our submissions to ILSVRC & COCO 2015 competitions, where we also won the 1st places on the tasks of ImageNet detection, ImageNet localization, COCO detection, and COCO segmentation.
[Metal]MTLLibraryをランタイムでコンパイルする

MTLLibraryは、SCNSceneKitなどでmetalシェーダのストアとして機能するコンポーネントです。
https://qiita.com/noppefoxwolf/items/ae302839f01ec4d820a1

基本的にはプロジェクトにmetalファイルを入れればアプリコンパイル時にコンパイルされてdefaultLibraryとしてバンドルされますが、時にはランタイムでコンパイルしたい場合もあります。
一つ例にあげるとすれば、実行時までマクロの値が決まらない時などが挙げられます。

```metal:source.metal.txt
#ifdef OUTLINE_WIDTH
return float4(0,0,1,1);
#else
return float4(1,0,0,1);
#endif
```

MTLLibraryを作るには、MTLDeviceのmakeLibraryメソッドを使います。

```swift

library = try device.makeLibrary(source: source, options: options)
```

sourceには、`Metal Shader Language`で書いたシェーダの文字列を、optionsには`MTLCompileOptions`を与えます。

マクロなどはoptionsで渡すことができます。

```swift
let options = MTLCompileOptions()
options.preprocessorMacros = [
  "OUTLINE_WIDTH" : NSNumber(1),
]
```
関西ぶらり旅 レポート　実習編 -visual studio code live share をやってみた-

# 今回のお題
今年の１月に遠征した関西ぶらり旅の実習レポートです。
第１回目は、 visualstudiocodeの live shareについて実際に演習でやってみたスクリーンショットのまとめになります

## 勉強会のページ

対象の勉強会「VS Code Meetup #2 - Live Share編(大阪会場)」
対象のセッション「Live Shareデモ（東京と大阪会場を繋いでみよう）」をやってみました

https://vscode.connpass.com/event/160088/

## 実習コーナー

今回、実習で使った参考ページはMicrosoftの公式ページを使っています。
大学科目の勉強中＋最新情報で確認をしたかったので、英語版で読んでいました

https://docs.microsoft.com/en-us/visualstudio/liveshare/quickstart/join


招待リンクが表示されたので、リンクをコピーして一人共有をしてみます。

https://twitter.com/kamedot/status/1228274472416792578/photo/2

ブラウザ上で、VisualStudioCodeを開くかどうかのポップアップが表示されました。
「Open Microsoft Visual Studio 2019」をクリックします
https://twitter.com/kamedot/status/1228274472416792578/photo/3

後は、VisualStudioが２つ立ち上がってそれぞれでログインした状態でアップされます


後日、リンク元の画像などを記事で編集予定です。
Add IP filtering on Laravel-Admin using Middleware

## Introduction
There are lots of post which introduces become accessible from only specific IP with Laravel.
However I couldn't find it adopt to Laravel-admin.

That's why I've noted here how to do it.

## Flow

1. Generate Middleware
2. Edit Middleware
3. Add Middleware to Kernel
4. Edit config file
5. Trust all proxy (If you use loadbalancer)

## Code

### 1. Generate Middleware
```
$ php artisan make:middleware CheckIpMiddleware
```

### 2. Edit Middleware

```app/Http/Middleware/CheckIpMiddleware.php

<?php
  
namespace App\Http\Middleware;

use Closure;

class CheckIpMiddleware
{
    public $whiteIps = ['xxx.xxx.xxx.xx'];

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $ip = self::getIp();
        if (!in_array($request->ip(), $this->whiteIps)) {
            abort('404');
        }

        return $next($request);
    }

    private function getIp(){
        foreach (array(
            'HTTP_CLIENT_IP',
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_FORWARDED',
            'HTTP_X_CLUSTER_CLIENT_IP',
            'HTTP_FORWARDED_FOR',
            'HTTP_FORWARDED',
            'REMOTE_ADDR'
        ) as $key){
            if (array_key_exists($key, $_SERVER) === true){
                foreach (explode(',', $_SERVER[$key]) as $ip){
                    $ip = trim($ip);
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE || FILTER_FLAG_NO_RES_RANGE) !== false){
                        return $ip;
                    }
                }
            }
        }
    }
}
```

### 3. Add Middleware to Kernel

```app/Http/Kernel.php
    protected $routeMiddleware = [
        ...
        'checkIp' => \App\Http\Middleware\CheckIpMiddleware::class,
    ];

```

### 4. Edit config file

```config/admin.php
    /*
    |--------------------------------------------------------------------------
    | Laravel-admin route settings
    |--------------------------------------------------------------------------
    |
    | The routing configuration of the admin page, including the path prefix,
    | the controller namespace, and the default middleware. If you want to
    | access through the root path, just set the prefix to empty string.
    |
    */
    'route' => [

        'prefix' => env('ADMIN_ROUTE_PREFIX', 'admin'),

        'namespace' => 'App\\Admin\\Controllers',

        'middleware' => ['web', 'admin', 'checkIp'], // Add checkIp here
    ],
```

### 5. Trust all proxy (If you use loadbalancer)

``` app/Http/Middleware/TrustProxies.php
    protected $proxies = '**'; // change to allow all proxy
```

## Refs
https://laravel.com/docs/6.x/requests#configuring-trusted-proxies
[SceneKit] SCNProgramを使ってSCNMaterialにシェーダーをかける

SCNMaterialの描画を変える方法はいくつかあるが、今回はSCNProgramを紹介する。
SCNProgramはSCNMaterialの描画を完全に制御することが出来る。
似たような機構にshaderModifierがあるが、こちらは既存の描画を拡張する意味合いが強いと思う。

SCNProgramは、その歴史的な事情からOpenGLESとMetalの両方のシェーダを受け取れるように出来ている。
特に`fragmentShader`プロパティや、`vertexShader`プロパティはOpenGLES用のプロパティである。

```swift
let program = SCNProgram()
program.fragmentShader
program.vertexShader
```

Metalのシェーダを渡す際はMTLLibraryを渡し、`fragmentFunctionName`と`vertexFunctionName`を指定する事になる。

```swift
let program = SCNProgram()
program.library = library
program.fragmentFunctionName = "myFragment"
program.vertexFunctionName = "myVertex"
```

肝心のMTLLibraryはアプリコンパイルのタイミングでコンパイルされているので次のように取り出すことが出来る。

```swift

let library = MTLCreateSystemDefaultDevice()!.makeDefaultLibrary()!
```

このようにして出来上がったprogramは、SCNMaterialのprogramプロパティにセットすることで動作します。

```swift
node.geometry.firstMaterial.program = program
```
SEO的に弱いTypescriptの!や?を使った演算子のまとめ

# はじめに
低級なプログラミング言語をメインで使っているのですが、たまにJavascript/Typescriptを書くことがあり、
先人の書いたコードの`??`や`！！`の意味がわからなくてググろうとするもなかなか検索に引っかからないため、
自分への備忘録としてまとめました。

キーワード：疑問符、感嘆符、ハテナ、ビックリマーク

## Null条件演算子 ?.

ex. ある変数entityがundefinedではないときにはentityのメソッドを実行し、undefinedの時は何もしないような場合

```typescript

// 単純に書くと
let entity: Entity | undefined

if (entity != null) {
    entity.Do()
}

// Null条件演算子を使うと一行で書ける
entity?.Do()

```
Null条件演算子を使った場合にその変数がNullだったらそのままnullを返してくれます。

## Null合体演算子 ??

ex. ある変数entityがundefinedではないときにはentity自体を返して、undefinedの時は規定の値を返す場合

```typescript

// 単純に書くと
let entity: Entity | undefined

if(entity == null)){
    return "This is undefined";
}else{
    return entity;
}

// Null合体演算子を使うと一行で書ける
return entity ?? "This is undefined"
```

## 二重否定の論理演算子 !!

ex. ある変数entityがundefinedかどうかを判定する場合

```typescript

// 単純に書くと
let entity: Entity | undefined

if (typeof entity === "undefined") {
    // Do something
}

// 二重否定を使うとシンプルに書ける
if (!! entity) {
   // Do something
|
```

どういうことが起こっているかというと、

```typescript

let entity: undefined

! entity // => true
!! entity // => !true = false となっている
```

## 非nullアサーション演算子 !.

TypeScriptコンパイラが自動的にその式を推論できない場合に、式がnullでもundefinedもないことを宣言できるらしい。

```typescript

// Compiled with --strictNullChecks
function validateEntity(e?: Entity) {
    // Throw exception if e is null or invalid entity
}

function processEntity(e?: Entity) {
    validateEntity(e);
    let a = e.name;  // TS ERROR: e may be null.
    let b = e!.name;  // OKAY. We are asserting that e is non-null.
}
```
フローとしてはnullはありえないけど、コンパイラがそれを判定できないので、Nullはありえないことをコンパイラに教えてあげるみたい。

https://typescript-jp.gitbook.io/deep-dive/intro/strictnullchecks#nullasshonnon-null-assertion-operator
未経験エンジニア転職においてRubyは不利

## 近年のエンジニアバブル
いたるところのネット広告では未経験からのプログラマーデビューを促すプログラミングスクールの広告で溢れている。
その勢いは日に日にましており、一体どれほどのスクールがあるのだろうか。もはや比較しようにも数が多すぎている気もする。まさにこの勢いは「スクールバブル」と呼ぶにふさわしいだろう。

## スクールで習得できる言語
スクールで教えている言語は大半が「Ruby」である。
機械学習の期待度の高まりもあり「Python」を教えているスクールも存在するが、基本スクール＝Rubyに感じられる。
Rubyは記述量も少なく、シンプルな構文で書くことができる。また、フレームワークはRuby on Rails一択であるし
型をいちいち指定してあげなくても良い。初学者がプログラミングを体系的に学ぶにはうってつけの言語だと思う。

## Rubyの市場価値
スクールでRubyを学んで卒業した学生は次に転職活動をすると思う。
ついに未経験エンジニアを目指して転生を試みるのだ、しかし実際に転職活動を始めた時に転職ポータルサイトなどでRuby、未経験などの募集を検索すると気づくのだが、Rubyの募集は実際かなり少ない。
Rubyが学びやすく、コードも描きやすいのは確かだが、それを理由にビジネスとしてのサービスを開発するのに使用するかどうかはまた別の話である。ミッションクリティカルなサービスでは型を指定できる言語の方が望ましいし、MVCモデルで記述できるフレームワークはPHPにも存在するのだ、確かにPHPの上位互換としての立ち位置でRubyは紹介されているが、一度PHPで開発したシステムをもう一度Rubyで作り直すのはコストが高すぎる。世の中にあるサービスはだいたいPHPかJAVAで作られているのだ、そして実際の仕事の発注は既存のシステム改修が多く、当然PHPやJAVAのエンジニアが求められる。
新たにRubyで開発を始めるシステムもあるが、だいたいそういう開発を行うのはスタートアップ企業が多く、スタートアップは未経験者を育てながら開発していく余力は無いところが多い。
以上のことからRuby未経験エンジニアの募集は少ない。

## スクールを卒業しても転職できない？
では転職はできないのかといいうとそういう訳では無い。
Rubyで一度開発経験があるかないかは、プログラミング経験なしと比べれば大きな差がある。入社後にPHPやJAVAを研修で習得することを条件に入社できる企業は多くある。自主学習でPHPかJAVAでサービスを作ったりしていればさらに受け入れてくれる企業は増えるだろう。
もちろんRubyをメインで使用している企業も多くあり、入社可能なこともあるので心配はいらない。
未経験でエンジニアになるのが目的であればRubyにこだわらず他の言語の募集もチェックすることも検討して見て欲しい
Python、stftime、strptimeの違い

#stftimeと、strptimの違いについてメモ

#（１）前提
datetimeモジュールのdatetiemクラスをインポートして、today()関数の結果を変数tに代入

```
from datetime import datetime
t = datetime.today
t
```
とすると、

```
datetime.datetime(2020, 3, 12, 23, 37, 45, 238787)
```
となる

#（２）datetime型　→  str型

```
str_t = t.strftime('%Y年%m月%d日/%H時%M分%S秒')
str_t
```
とすると、

```
'2020年03月12日/23時37分45秒'
```
となる
#（３）str型　→ datetime型　

```
time_t = datetime.strptime(str_t, '%Y年%m月%d日/%H時%M分%S秒')
time_t
```
とすると、

```
datetime.datetime(2020, 3, 12, 23, 37, 45)
```
となる。
Pi Imagerを使ってヘッドレスなセットアップ

気が付いたら公式からOSの書き込みソフトが出ていたので、
それを使ってOSのインストールからssh接続でWi-Fiに接続するまでをメモ程度に書いていきます。
注: Windows 10で作業をしているので他OSでは少し違う場合がありますが、そのあたりは臨機応変にお願いします。
#必要なもの
- パソコン (Windows, Mac, Ubuntuのどれか
- microSD (8GB以上が望ましい)
- microSDと接続するSomething
- Raspberry Pi 3 Model B+
- 5VのACアダプタ(microUSB端子、3A以上)
- ひまつぶしできるもの

#Pi Imagerのインストール
https://www.raspberrypi.org/downloads/ からRaspberry Pi Imager for (OS名)をダウンロードします。
imager.exe を実行するとウィザードらしきもの👇が出てくるのでそれに従ってインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285263/6ced1000-bac3-c8c8-a71d-d64e5e176a50.png)
Installを押すと自動でインストールしてくれます。(WindowsであればProgram Files(x86)にインストールされます
インストールが終わったら起動してみてください。
👇のようなウィンドウが出れば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285263/2e94d31f-d567-4426-0a8f-991adc14fd31.png)

# OSの書き込み
## SDカードのフォーマット
まずmicroSDカードをPCと接続します。
接続できたら、Imagerを起動し、Operating System からEraceを選択し、SD cardから今回使用するSD cardを選ぶと、WRITEというボタンが出現します。それを押すと、勝手にFAT32でフォーマットしてくれます。
Eraceはゴミ箱が目印です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285263/ad38ef8a-3471-a3b7-9edb-84433a1baa5c.png)
##OSの書き込み
フォーマットが完了したら、いよいよOSの書き込みをしていきます。
今回はデスクトップ環境は必要ないので、Operating SystemからRaspbian(Other)、Raspbian Liteを選択します。
そしたら、書き込む場所があっているのかを確認し、OSを書き込んでいきます。
ちょっと時間がかかるのでちょっと休憩です。
##SSH接続の設定
OSが書き込めたら、bootフォルダにwpa_supplicant.confとssh(拡張子なし)というファイルを作成します。
wpa(略には

```wpa_supplicant.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="hoge"
    psk="huga"
}
```

hogeには使用するネットワークのSSID、hugaにはネットワークの暗号化キー(パスワードが)入ります。

書き込めたら、SDカードを取り出してRaspberry Piにぶち込んでやります。

#Raspberry Piと接続
Raspberry Piに電源を投入して、ターミナル等で`arp -a`とやるとPhisical Addressがb8-27から始まるやつがあります。
そいつのIPアドレスにsshするとパスワードを入力させられるので`raspberry`と入れると、SSH接続できます。やったね

MACとかだと`ssh pi@raspberrypi.local`で入れるみたいです。

初期設定等はここでは扱わないのでいい感じに。

#参考
[RaspberryPi Raspbian ヘッドレスインストール](https://qiita.com/nori-dev-akg/items/a8361e728a66a8c3bdba)
[Raspberry Pi Imager を使って microSD カードをフォーマットする](https://qiita.com/inouetakuya/items/4d95a7c71d0a56047934)
Python、fromとimport、asについて

#pythonで使用するfromとimportの違いをメモ（例としてtoday関数を使い、２通りの方法を記述）

##（１）datetimeモジュール（ファイル）をインポートするのみ
datetimeモジュールの、datetimeクラスのtoday関数を使う、という記述をする

```
import datetime
datetime.datetime.today()
```
結果として

```
datetime.datetime(2020, 3, 12, 23, 21, 41, 756354)
```
となる。

##（２）datetimeモジュール（ファイル）とdatetiemクラスをインポートする
上記の例ではモジュール名.クラス名とするのが面倒です。そんなときはimportだけでなくfromも使ってインポートします。
from モジュール名 import クラス名（もしくは関数名や変数名）
datetimeクラスのtoday関数を使う、という記述をする


```
from datetime import datetime
datetiem.today()
```
結果は同様に

```
datetime.datetime(2020, 3, 12, 23, 21, 41, 756354)
```
となる。

##（３）おまけ
asを使うとライブラリ名（モジュール名）を好きな言葉で使うことができる。

```
import datetime as t
t.datetime.today()
```
結果は同様に

```
datetime.datetime(2020, 3, 12, 23, 21, 41, 756354)
```
となる。
今更ながらWPFに置き換えてみる（6）

#Canvasを利用してのアナログ時計の描画
VB版ではミニなアナログ時計をNotifyIconに入れたり、時報のフォームに表示したりするのに
GDI使って描画をしてました。とりあえず何も考えずLineやEllipseで描画してテスト画面にだしてみますと、こんな感じ。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590512/d3ff6c4b-8965-c916-bf89-1199aec3d901.png)

んーベクター画像はやはりきれいですね。
DropShadowとかも設定できてすばらしい。

```C#
canvasへの描画部分

            //Drop Shadow効果設定
            var DSE = new DropShadowEffect();
            DSE.BlurRadius = aCanvas.Height / 50;
            DSE.Direction = 270;
            DSE.Opacity = 0.2;
            DSE.ShadowDepth = aCanvas.Height / 20;
・・・中略
            //時針描画
            Line hhLine = new Line();
            hhLine.Stroke = Brushes.White;
            hhLine.StrokeThickness = aCanvas.Width / 20;
            if (hhLine.StrokeThickness < 1)
            {
                hhLine.StrokeThickness = 1;
            }
            hhLine.X1 = aCanvas.Width / 2;
            hhLine.Y1 = aCanvas.Height / 2;
            hhLine.X2 = hhHandEdPt.X;
            hhLine.Y2 = hhHandEdPt.Y;
            hhLine.StrokeStartLineCap = PenLineCap.Round;
            hhLine.StrokeEndLineCap = PenLineCap.Round;
            hhLine.Effect = DSE;
・・・中略
            aCanvas.Children.Add(hhLine);
```
#画面のトランジションテスト
モチベーション維持のために前回のテストアプリを加工し、左上の小アイコン（１６×１６程度）に現在のアナログ時計イメージをセットしそれをクリックした場合プロセスアイコン的なサイズにフォームの大きさを変更しながら小アイコンを全面にする、という動きを設定してみました。
こんな感じ。
![TestApp2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590512/2b47288e-c32c-a76b-4712-4653435a45a7.gif)


クロックを書き込んだCanvasをscaletransform＋アニメーションさせて、同時にWindowのサイズをぐりぐり変更しているのですが、当然シンクロもしていないし、なにより遅い。おそすぎる。
Widthとheightの変更が交互に行われているのが目で追えるレベル。
モチベーションが逆に下がる結果となりました。
React NativeにGoogle AdMobを設定しよう(for iOS)

# はじめに
アプリで収益を上げるためには広告が手っ取り早いのですが、入れるために少しだけハマりポイントがあったため、ここに記事を残します。

Firebaseへのリンクは出来たり出来なかったりよく分からない上に(昨日できなかったけど、今日できた)、上手く広告が出ませんでした。
そのため、今回はFirebaseなしでやります。

Androidはまだやってないので、今回はiOSだけです。
多分Androidでも特に困らないと思いますが、やってないので保証は出来かねます。

# 環境
React Native 0.61.5
Cocoa Pod

Expoでも作れるらしいですが、そちらはやってないので書きません。

# Admobの登録
https://www.google.com/intl/ja_jp/admob/index.html

上記URLより有効化します。
また、アプリを作成してどんな広告を出すかを設定してください。
特に迷うことなくできる感じなので、ここでは割愛します。

1つだけ注意としては広告配信準備が整うまで見れないので、先にアプリ作って実装した方が良いです。
すぐに準備は整いません。（どれくらいで準備されるかはわかりません。アプリ作る時点くらいで作っておいて困るものでもないので、なるべく早く作った方が楽です）

# Firebaseを使わないAdmobの表示
https://github.com/sbugert/react-native-admob

ライブラリが優秀なので、上記のライブラリを使用するのが一番楽です。
手順もREADME通りにやれば問題ないのですが、注意としてReact Native 0.60から手動リンクせずにpodを使うこととなるためそこだけ注意です。
また、react-native-admobの`pod install`では`Google-Mobile-Ads-SDK`が入らないので、`pod 'Google-Mobile-Ads-SDK'`を自力で`ios/Podfile`に記述することだけ忘れないでください。

あとは公式に従ってComponent使って起動すればテストの広告が見れるようになります。

# 終わりに
Firebaseつなぐ方が良さげですが、上手く行かない理由が分からなくて悲しい。
ただ、なくても困らない（オプション扱い）ので、駄目な時はなしでいきましょう。
EC2にSSH接続可能ユーザーを追加する

# 内容
EC2へSSH接続する際に公開鍵認証を使用して、Amazon Linux2であればec2-user以外で
接続できるようにするため新しいユーザーを作成する。

# 対象機器
EC2(Amazon Linux2)

# 参考手順
手順は以下のAWS公式を参考にしています。
[Amazon EC2 を使用してキーペアを作成する](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-key-pairs.html#having-ec2-create-your-key-pair)
[ユーザーアカウントを作成する](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/managing-users.html#create-user-account)

# ハンズオン
## キーペアの作成(AWSマネジメントコンソール使用)
**EC2へ接続するキーペアが存在していれば実施不要です。**

AWSマネジメントコンソールへログインし、[サービス]⇒[コンピューティング]⇒[EC2]を選択します。
![ss_000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510919/b48ddbf8-4b3c-c728-096c-761a67dde21d.jpeg)

左側メニューより、[ネットワーク&セキュリティ]⇒[キーペア]を選択します。
![ss_001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510919/ca1151d9-d80b-e6d7-6319-1a3913ce0597.jpeg)

キーペア一覧画面よりキーペアの作成を押下します。
![ss_002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510919/7206eca1-7473-c909-d7bc-d4781cf5b150.jpeg)

[名前]と[ファイル形式]を[キーペアを作成]を選択して[キーペアを作成]を押下します。
※今回はpemを選択します。
pemとppkについては下記サイトが分かりやすかったです。勉強になりました。
[pemファイルとppkファイルの相互変換](https://ryoheihey.com/information-technology/pem-ppk-2/2019/09/14/525/)
![ss_003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510919/082c3d9f-d989-5aa2-8aef-fa1b25d3a8a5.jpeg)

## ユーザー作成&設定(Linux)
EC2へ接続して、rootユーザーへ切り替えます。

### ユーザー作成
```
# adduser nonZy
```
### パスワード設定
```
# passwd nonZy
Changing password for user nonZy.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
```
### 作成したユーザーへ切り替え
```
# exit
logout

$ su - nonZy
Password:

$ whoami
nonZy
```

### ssh/authorized_keysの設定
#### 作成したユーザー(nonZy)のhomeディレクトリにいることを確認
```
$ pwd
/home/nonZy
```

#### .sshディレクトリの作成&設定
```
$ mkdir .ssh
$ ls -la
total 16
drwxrwxr-x 2 nonZy nonZy   6 Mar 12 01:09 .ssh
$ chmod 700 .ssh
$ ls -la
total 16
drwx------ 2 nonZy nonZy   6 Mar 12 01:09 .ssh
```
#### パブリックキーの取得
EC2へ接続する際に使用しているキーペアをサーバ上へ転送します。
今回は**/tmp**配下に配置しました。

```
$ ssh-keygen -y -f /<キーペア格納先>/<作成したキーペア名>.pem 
ssh-rsa ...******<ズラーッと文字列が並びます>******...
```

#### authorized_keysファイルの作成

```
$ touch .ssh/auhthorized_keys
$ chmod 600 .ssh/authorized_keys
$ ll .ssh
total 0
-rw------- 1 nonZy nonZy 0 Mar 12 01:12 authorized_keys
$ vi .ssh/authorized_keys
```
viコマンドでssh-keygenコマンドで取得したパブリックキーを貼り付けます。

# 終わり
作成したユーザーでEC2へ接続できるようになった。
低スペ中古ノートPCにChromiumOSを入れてみる

##はじめに
部屋を掃除していたら使ってない古いPCが出てきて、捨てるのはもったいない気がして、Windows7のサポートも終了しているし、せっかくなのでChromeOS(ChromeiumOS) を入れて遊んでみることにしました。
ChromiumOSにはいくつか種類があるらしいが今回はCloudReadyをつかってみる

##PCのスペック
2012年製DELL　Inspiron15(N5050)
CPU:PentiumB960（2.20GHz、1333,2Mキャッシュ）
RAM:4GB
HDD:500GB
OS:Windows7(なぜか起動せず)

##準備
まず、ブート用のUSBを作成するので、[ここから](https://www.neverware.com/freedownload)CloudReadyをダウンロードする。
Windowsからは「cloudready-usb-maker」を使ってブート用USBを作成するみたいだが、なぜかうまくいかない…

代替手段としてMac・Chrome用のページから「cloudready-free-78.4.3-64-bit.zip」をダウンロードして解凍する。
解凍したファイルの拡張子をisoにしてイメージファイルにする。以前、ラズパイを使うためにSDにRaspbianOSをSDカードに書き込むために使った「[Etcher](https://www.balena.io/etcher/)」を使ってCloudReadyをUSBに書き込む。
![qita.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584794/444c10a5-906c-1178-2e68-76a234cacbb7.png)
書き込みが完了したら完成。

##インストール
起動時にF12を連打してブート先をUSBにして起動。
諸設定を済ませてログインしたら、とりあえずは使えるがブート先をHDDにする必要があるのでPC内にインストールする。
デスクトップ画面の右下にある時計をクリックしタスクトレイを開く、そのなかにある「Install OS」をクリックしたら注意事項等が出てくるので、「INSTALL CloudReady」をクリックする。そしたらインストールが始まるのでしばらく待っている。（画像がなくてわかりにくい説明で申し訳ありません…）
完了したら勝手に電源が切れてるので、起動し直してログインし直したらインストール完了！

###おまけ
#####ターミナルを使ってラズパイにshh接続してみる。
CloudReadyではデフォルトでデベロッパーモード？になってるらしいので、ややこしいモード変更の必要なくshellコマンドが使えるそうです。(shellコマンドをよくわかっていない)
「ctrl+alt+T」でターミナルを開き、「shell」と入力するとbashが起動するので、あとはいつもの手順でssh接続でラズパイに接続する。

こんな感じ
![qiita.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584794/88a0f7af-ee84-148d-4c0c-0397c1ced6d0.png)

##最後に
かなり低スペのPCだけどもOSを載せ替えたら思ってた以上にサクサク動くので驚き
さらにFlatpakを使えばLinux向けのアプリも使えるので、思った以上に広い用途に使えうそう…
PCのリユースにChromiumOSは良いんじゃないだろうか？
kintone 関連レコード集計プラグインによるタイムカード月次集計

関連レコード集計プラグインで、タイムカードアプリを月次集計する例です。
集計先レコードが無い場合にレコード追加する新機能を使ってみます。
タイムカードアプリに入力・承認したタイミングで、月次集計が行われます。

# 概要

[関連レコード集計プラグイン](https://qiita.com/rex0220/items/8cbe764670b0e6431a42) Ver.11 で、集計先レコードが無い場合にレコード追加する機能を使って月次単位に自動集計します。
勤務時間の合計とステータス毎の件数を集計します。


<img width="1245" alt="2020-03-12_22h44_24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/48bcc15d-d23d-7a58-505a-1fd93b6821e6.png">


# アプリ構成

- タイムカードアプリ：　kintone ストアアプリから作成
- タイムカード月次集計アプリ：　新規作成

## タイムカードアプリ

kintone ストアアプリから作成のままです。

<img width="825" alt="2020-03-12_22h26_10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/95cb5eab-da70-d5c9-3490-635cac2c95be.png">

## タイムカード月次集計アプリ

新規作成して、項目を配置します。
「勤務時間」は、集計先項目。勤務時間（時間）は、時間単位の表示用。

- 申請者：　ユーザー選択
- 対象年月：　日付
- 勤務時間：　数値
- 勤務時間（時間）：　計算　(勤務時間*60)
- 未処理（下書き）：　数値
- 上長確認中：　数値
- 承認：　数値
- 差し戻し：　数値

<img width="832" alt="2020-03-12_22h27_31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/76b5cde8-e8b8-16be-34bf-6b0ec994b01b.png">


# タイムカードアプリの関連レコード集計プラグイン設定

タイムカード月次集計アプリを集計先に設定します。

<img width="991" alt="2020-03-12_22h35_58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3d60ccb4-f994-b6f7-2a9a-3b39b964ef32.png">

## 対象アプリ条件

集計のキーとなる申請者と対象年月を指定します。

- 申請者： in SEL_CODE(申請者,"array")
- 対象月： = DATE_FORMAT(日付,"YYYY-MM-01")

<img width="829" alt="2020-03-12_22h38_50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/f70f4a58-1efe-c69d-66e5-ee4260d41479.png">

## 集計条件

集計元のタイムカードアプリの抽出条件を指定します。

- 申請者： in SEL_CODE(申請者,"array")
- 日付： >= DATE_FORMAT(日付,"YYYY-MM-01")
- 日付： <= DATE_ENDOF(日付,"month","YYYY-MM-DD")


<img width="831" alt="2020-03-12_22h39_19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a09010c5-5430-4170-0fc5-7f1183cb616d.png">

## 集計順

今回は、合計・カウントだけなので、集計順は影響しませんが、とりあえず日付順とします。

<img width="451" alt="2020-03-12_22h39_44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/586c40fb-3444-11e2-923f-6a40a1b291b4.png">


## 集計項目

「集計先レコードが無ければ追加」をチェック
項目の「レコード追加時に設定」をチェックすると、レコード追加時のみ設定されます。

- 申請者： in SEL_CODE(申請者) ※レコード追加時に設定
- 対象月： DATE_FORMAT(日付,"YYYY-MM-01") ※レコード追加時に設定
- 勤務時間： DURATION_AS(計算,"minutes")
- 未処理（下書き）：　IF(ステータス=="未申請（下書き）",1)
- 上長確認中：　IF(ステータス=="上長確認中",1)
- 承認：　IF(ステータス=="承認",1)
- 差し戻し：　IF(ステータス=="差し戻し",1)


<img width="783" alt="2020-03-12_22h40_08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/976fe28c-561c-7ceb-e852-a37347520799.png">


# あとがき

タイムカードアプリに入力・承認したタイミングで、月次集計が行われると、リアルタイムでチェックが出来ますので、かなり効率改善につながるのではないでしょうか？
同じような集計処理にもいろいろ応用できそうです。
Dartの制御文（繰り返し）

# Dartの制御文（繰り返し）

繰り返し制御文は他のプログラミング言語と大差ない様子。

## for文
```dart
List<int> list = [1, 2, 3];
// for
for (int i = 0; i < list.length; i++){
	print(list[i]);
}
```

```dart
// 実行結果
1
2
3
```

## forEach文

```dart
List<int> list = [1, 2, 3];
Map map = { 1 : 'first',
			2 : 'second',
			3 : 'third',
}; 
// forEach
list.forEach((int value){print(value);});
map.forEach((key,value){print('$key : $value');});

```

```dart
// 実行結果
1
2
3
1 : first
2 : second
3 : third
```

## for-in文

```dart
List<int> list = [1, 2, 3];
// for-in
for(var value in list){
	print(value);
}
```

```dart
// 実行結果
1
2
3
```

## while文

```dart
List<int> list = [1, 2, 3];
var index = 0;
while(true){
	if (index >= list.length){
		break;
	}
	print(list[index]);
	index++;
}
```

```dart
// 実行結果
1
2
3
```

## do-while文

```dart
List<int> list = [1, 2, 3];
var index = 0;
do {
	print(list[index]);
	index++;
} while(index < list.length);
```

```dart
// 実行結果
1
2
3
```



[参考サイト]

>[Flutter入門のためのDart入門](https://qiita.com/teradonburi/items/913fb8c311b9f2bdb1dd)
[ネタ]強制的にLGTMをいいねに戻す方法[Chromeエクステンション不要]


# LGTMよりいいねが好き

つい最近、QiitaのいいねがLGTMになりました。しかし世の中には、

- LGTMよりいいねが好き
- いいねがなければ生きていけない

そんな方も多いはずです。
そんな方に朗報。
ブラウザのお気に入りのリンクに追加するだけでボタンの文字を「いいね」に変えてしまうコードを作ってみました。
適当なサイトをお気に入りに追加し、下記のコードをリンクに設定するだけです。

```JavaScript
javascript:(()=>{document.getElementsByClassName('it-Actions_item-like')[0].children[1].style.fontSize='12px';document.getElementsByClassName('it-Actions_item-like')[0].children[1].innerHTML='いいね';document.getElementsByClassName('it-Footer_like')[0].children[0].children[0].innerHTML='いいね';})();
```

あとはQiitaの記事が表示されている状態でお気に入りの項目をクリックするだけです。
ブックマークバーを使用すると使い勝手がいいようです。


~~クロームなどでお気に入りバーを使っていらっしゃる方は以下のリンクをお気に入りバーにドラッグ＆ドロップするだけです。~~
追記：Qiitaのセキュリティ上さすがにこのやり方は使えないみたいです。

[いいね]("javascript:(()=>{document.getElementsByClassName('it-Actions_item-like')[0].children[1].style.fontSize='12px';document.getElementsByClassName('it-Actions_item-like')[0].children[1].innerHTML='いいね';document.getElementsByClassName('it-Footer_like')[0].children[0].children[0].innerHTML='いいね';})();")

下記のように、LGTMボタンが「いいね」に変わりました。

<img width="135" alt="スクリーンショット 2020-03-12 22.52.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112409/ddedea66-d308-436c-251b-b9bd00efd6f4.png">


追記：
調べたところ、すでにChromeエクステンションを用いた方法で同じ様な記事を書いている方がいること、そしてその方のほうがよりリアルにいいねボタンを再現していることが判明しました。そこでこちらの記事のタイトルに「Chromeエクステンション不要」という文言を追加しました。

[LGTMを戻す](https://qiita.com/sapi_kawahara/items/4e05845e285ac087feb5)
Java言語で学ぶデザインパターン入門の4章まとめ

お久しぶりです。白々です。
先日エンジニアの先輩にデザインパターンをご存知でない！？という冷静なツッコミを頂き、その後結城浩さんが書かれた「Java言語で学ぶデザインパターン入門」を渡されたので勉強することにしました。
ただ、本を一読しても覚えられないので覚書として記事にしようと思いました。
今回で4回目です。
完走できるように頑張ります。
また、「Java言語で学ぶデザインパターン入門」には、サンプルプログラムも有りますが、著作権の都合上省かせて頂きます。御了承ください。

前回は、「Template Methodパターン」に関しての記事を作成しました。
前回の記事は、以下です。
https://qiita.com/sirajirasajiki/items/53e1d2aea166190f9a6f

今回は、「Factory Methodパターン」に関して記載したいと思います。
また、「Factory Methodパターン」には、サンプルプログラムも有りますが、著作権の都合上省かせて頂きます。御了承ください。

#第4章 Factory Method-インスタンス作成をサブクラスに任せる
「Java言語で学ぶデザインパターン入門」には、
>Factory Methodは、簡単にいうとTemplate Methodパターンをインスタンス生成に適用した物

だそうです。

イメージしにくい人もいると思うので、例を記載します。
工場を思い浮かべてみてください。
工場では、製品が作成されています。
しまむらやユニクロなどの大手のチェーン店では、Tシャツ大体工場とかで作成されていることが多いですよね？
大きさは、大体Sサイズならこれくらい、Mサイズならこれくらいとサイズごとに大体大きさが決まっていると思います。
しかし、材質や、デザインは、企業によって異なると思います。
工場では他にも、パソコン等も作成されていると思います。
パソコンだったら、メモリは16GBでSSDかHDDかみたいに分かれていくと思います。
このように、工場内で何を作っても製品ですよね？
工場で何かを作ることをスーパークラスとすると、Tシャツ工場は、サブクラスとなります。
しかし、パソコン工場というサブクラスも作ることができます。
抽象化したクラスを使うことで共通の概念を持った全く違うサブクラスを作成することができます。

このように、インスタンスをどのように作成するかをスーパークラス側で決めておき、具体的な処理をインスタンスに任せることによってインスタンスの生成の枠組みとインスタンスの生成とを分けて考えることができます。
また、具体的な処理をインスタンスに任せることによって、スーパークラスは、インスタンスに依存しない状況が作れます。

##Factory Methodを使う時の注意事項
「Factory Methodパターン」で作成したサブクラスは、スーパークラスにインスタンスの作り方を決められます。
なので、スーパークラスをちゃんと理解する必要があります。

##Factory Methodを使った例
「Java言語で学ぶデザインパターン入門」にもあった工場の例を使ってクラス図とPythonのコードを作成します。
今回は、工場クラスと製品クラスを作成し、それぞれを継承したパソコン工場クラスとパソコンクラスを作成します。
工場クラスには、製品を作成する「createProduct」という抽象メソッドと、作成した製品を登録する「registerProduct」という抽象メソッドが宣言されており、この2つの抽象クラスはサブクラスで実装します。また、「create」という「createProduct」を使って製品を作成し、「registerProduct」で製品を登録するという流れを実装したメソッドがあります。
パソコン工場クラスは、工場クラスを継承し、「registerProduct」と「createProduct」を実装し、どの人が購入したのかを示す「get_owners」というメソッドを継承しています。

製品クラスには、作成された製品を使う「use」という抽象メソッドのみ実装されています。
パソコンクラスは、製品クラスを継承し、「use」を実装し、自身のインスタンスを作成するメソッドと、誰に送るのかを取得する「get_owner」メソッドが実装されています。実際に実装する場合は、送り先や、法人か個人か、パソコンのスペック等を取得したり登録できたりするべきではありますが、今回はFactory Methodを使った例なので、行いません。

###クラス図
![factory_method.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521126/bb14ec64-31b5-11b3-c26e-0f4bd2795cc0.png)

このクラス図は、PlantUMLというもので記載しています。
私が、書いたPlantUMLのコードは以下のGitHubに記載がありますのでReadMeを読んでお使いください。
factory_method.txtです。
https://github.com/sirajirasajiki/design_pattern_uml/tree/master/template_method
PlantUMLのインストール方法と使い方に関しては、後述のappendixに記載しています。
###クラス図を元にPythonで実装
以下に実装したコードを公開しています。Python 3.7で実装しました。
https://github.com/sirajirasajiki/design_pattern_python/tree/master/FactoryMethod
#まとめ
スーパークラスでインスタンスをどのように作成するかを決め、サブクラスで具体的な処理を記載する「Factory Methodパターン」について学びました。

#第4章感想
Factory Methodパターンだけなく、基本的にパターンを使うときは、スーパークラスをちゃんと理解する必要があると思いました。
なので、スーパークラスにはどのような意味なのかをコメントで書こうと思います。
~~説明で使った例は、後日Pythonで実装しようと思います。~~
Pythonで実装しました。


#最後に
何か間違っているところがあれば、ご指摘していただけると嬉しいです！

#appendix
##次回の記事
https://qiita.com/sirajirasajiki/items/532d33fd823e52ab0d1a

##PlantUMLに関するサイト
PlantUMLのインストールの時にお世話になったサイトは以下です。
https://qiita.com/kohashi/items/1d2c6e859eeac72ed926
PlantUMLを書くときにお世話になっているサイトは以下です。
https://qiita.com/ogomr/items/0b5c4de7f38fd1482a48
ksnctf 19 ZIP de kure

#ksnctf 19 ZIP de kure

* 問題
    * http://ksnctf.sweetduet.info/problem/19
* ZIPファイル回答
    * パスワードがかかったファイルが置かれている
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416717/d916ae9a-e36f-f7b8-0b82-d2057b3b4278.png)

* binwalk
    * 最後にHintが出てくる
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416717/21c658a7-6c61-3deb-517a-02dc8195d829.png)

* known-plaintext attacks
    * 既知平文攻撃
    * 暗号化前と暗号化後のファイルを使って、パスワードを割り出す
    * zipにネット上に落ちてるファイルとか入れてたら既知平文攻撃によりパスワードが分かってしまう

* 既知平文攻撃を試す
    * Standar-lock-key.jpgで画像検索
        * 色々出てくるので、これのどれかを使えば良さそう
        * 250KBくらいのやつを使う
    * pkcrack
        * 既知平文攻撃のためツール
        * windowsでやろうとして実行したら64ビットwindowsには対応していないと言われたので
        * Linuxでやる
        
            ```
$ ./pkcrack -C ../../flag.zip -c Standard-lock-key.jpg -p ../../Standard-lock-key.jpg -d answer.zip
```
            *　answer.zipがパスワード解除済みのファイルをして生成される
            *　flag.htmlにアクセスしてフラグゲット


* 参考リンク
    * http://www.stockdog.work/entry/2017/07/09/131657 
    * https://n-lab.site/?p=102
    * https://www.unix-ag.uni-kl.de/~conrad/krypto/pkcrack.html