OmniAICreator/Qiita-1.07M huggingface dataset:
【devise】confirmableを適用時のemailの変更確認をスキップする

`config/initializers/devise.rb`を以下のように変更して保存。

````diff:config/initializers/devise.rb
  ...

  # If true, requires any email changes to be confirmed (exactly the same way as
  # initial account confirmation) to be applied. Requires additional unconfirmed_email
  # db field (see migrations). Until confirmed, new email is stored in
  # unconfirmed_email column, and copied to email column on successful confirmation.
- config.reconfirmable = true
+ config.reconfirmable = false

  ...
````

この時点でサーバーを起動していたなら再起動する。これでユーザー情報を編集する際に、メールアドレスをメールによる確認作業なしで変更できる。

もし`users`テーブルに`unconfirmed_email`カラムが残っているなら、不要なので削除する。

````terminal
$ rails g migration remove_unconfirmed_email_from_users unconfirmed_email:string
$ rails db:migrate
````
bookedの入力画面をカスタマイズする

[www.bookedscheduler.com](https://www.bookedscheduler.com/) 

予約の作成で表示される文字列の改造ができた。（バージョン2.7.4のお話です）

C:\Apache24\htdocs\booked\lang\ja_jp.php

```php:ja_jp.php

/* $strings['ReservationTitle'] = '件名';*/
$strings['ReservationTitle'] = '所属　氏名';

/*$strings['ReservationDescription'] = '説明';*/
$strings['ReservationDescription'] = '説明文　入力者を記入';
```
こんな感じ
TypeScriptの型は幻ではない！　~ 型宣言を実行中のチェックに使う ~

# TypeScriptの型は幻ではない！　~ 型宣言を実行中のチェックに使う ~

## 幻を現実とする

　TypeScriptでは静的な型付けが可能です。しかしいくら型を宣言しようとも、簡単に内容を誤魔化すことができてしまいます。厳密に型チェックを行うのであれば、コンパイル時だけでなく、実行時にも型をチェックしなければなりません。もちろん手動で一つ一つ書いていけば良いのですが、それでは面倒です。

　今回はできるだけ簡単にクラスのメソッドに実行時の型チェック機能を付けるという内容をやっていきます。

##事前準備

　TypeScriptの設定のうち、デコレータとメタデータを有効にします。これによって型情報がコンパイル時の出力ファイルに埋め込まれるようになります。

``` json:tsconfig.json
{
  "compilerOptions": {
   "experimentalDecorators": true
   "emitDecoratorMetadata": true 
  }
} 
```

## ソースコード

　型チェック機能の実装部分です。デコレータでメソッドに割り込みをかけて、メタデータの型情報と照合します。

```.ts
import "reflect-metadata"; //npmから追加インストールの必要あり

//型のチェック
function isType(type: object, value: unknown) {
  switch (type) {
    case Number:
      if (typeof value !== "number") return false;
      break;
    case String:
      if (typeof value !== "string") return false;
      break;
    case Boolean:
      if (typeof value !== "boolean") return false;
      break;
    case Array:
      if (!(value instanceof Array)) return false;
      break;
    case Function:
      if (!(value instanceof Function)) return false;
      break;
  }
  return true;
}
//型チェック用デコレータ
function CHECK(target: any, name: string, descriptor: PropertyDescriptor) {
  const ptypes = Reflect.getMetadata(
    "design:paramtypes",
    target,
    name
  ) as object[];
  const rtype = Reflect.getMetadata(
    "design:returntype",
    target,
    name
  ) as object[];
  return {
    ...descriptor,
    value: function(...params: unknown[]) {
      if (ptypes.length !== params.length) throw "引数の数が不正";
      const flag = ptypes.reduce((a, b, index) => {
        return a && isType(b, params[index]);
      }, true);
      if (!flag) {
        throw "引数の型が不正";
      }
      const result = descriptor.value.apply(this, params);
      if (!isType(rtype, result)) throw "戻り値の型が不正";
      return result;
    }
  };
}
```

　サンプル用にクラスを作り、デコレータを設定したメソッドを用意します

```ts
//テスト用クラス
class Test {
  @CHECK //これを付けると実行時に引数と戻り値の型がチェックされる
  func01(a: number, b: string, c: boolean): number {
    console.log(a, b, c);
    return 0;
  }
  @CHECK
  func02(a: number, b: string, c: boolean): number {
    console.log(a, b, c);
    return "A" as never; //戻り値をstring型にする
  }
}
```

　実際に動かすと、引数や戻り値のチェックができていることが分かります。

```ts
//インスタンスの作成
const test = new Test();

//真っ当に実行
test.func01(0, "A", true);  //OK

//引数の数を間違える
try {
  (test.func01 as any)(true); //例外 "引数の数が不正"
} catch (e) {
  console.error(e);
}

//引数の型を間違える
try {
  (test.func01 as any)(0, 10, true); //例外 "引数の型が不正"
} catch (e) {
  console.error(e);
}

//戻り値が間違ったメソッドを呼び出す
try {
  test.func02(0, "A", true); //例外 "戻り値の型が不正"
} catch (e) {
  console.error(e);
}

```

## チェックの限界

　単純な型しかチェックできません。複合的な型のチェックも出来ません。複合的な型は作ったとたんにメタデータがObject型になってしまうので判定しようがないのです。ということでObject型の判定はあえてやっていません。これ以上の領域に進むならCompilerAPIを使って、元ソースやd.tsから情報を引っ張ってくるという愉快な作業をすることになります。

## まとめ

　TypeScriptでは使いどころを見つけるのが難しいデコレータと、ますます使い道が難儀なメタデータを取り扱ってみました。もともとこの機能は**Experimental Options**となっているので、もしかしたらもっと高機能な何かが実装される日が来るのかもしれません。
アンチパターン：Railsで外部キーとassociation名は同じにしない

### 要約
- `belongs_to :name` と`foreign_key :name`が同じだと、その逆のhas_manyをとるときにどうがんばってもうまく取れなかった
- 同じにしない
- 外部キーには`_id`つける

### 詳細
- 以下のコードだと`to_messages`、`from_messages`がとれない

```ruby
class User < ApplicationRecord
  has_many :to_messages, class_name: 'Message', foreign_key: 'to', dependent: :destroy
  has_many :from_messages, class_name: 'Message', foreign_key: 'from', dependent: :destroy
end

class Message < ApplicationRecord
  has_many :to, class_name: 'User', foreign_key: 'to'
  has_many :from, class_name: 'User', foreign_key: 'from'
end

>Message.last.to
=>#<User id: 373...>
>User.last.to_messages
=>[]
```

- has_manyの名前を変えたらいけた

```ruby
class Message < ApplicationRecord
  has_many :to_user, class_name: 'User', foreign_key: 'to'
  has_many :from_user, class_name: 'User', foreign_key: 'from'
end
```

- そもそも`foreign_key`は`_id`がいいね
- 自分では慣例的にやらないけどレビューであがってくることはあるので覚えておく
効果的な時間管理術「ポモドーロ・テクニック」


# ポモドーロ・テクニックとは、  
> エンジニアやデザイナーなどクリエイティブで高い集中力が必要な人を中心に取り入れられている

# 効果向上ポイント  

## 時間管理を徹底する  

> 作業時間はタイマーを見ながら正確に測りましょう。タイマーが鳴ったら、作業が途中でも必ず中断して休憩に入ることが大切です。これは集中力を維持し、作業時間や業務量を正確に見積もるためです。

> ただし、集中力には個人差がありますので、作業時間の長さを変更することは可能です。例えば、タスクの内容によっては25分でも長いことがあるかもしれませんし、50分は集中力が続くという人もいます。

> 一度決めた作業時間さえ正確に守れれば、1ポモドーロを絶対に「25分+5分」にしなければならないということはありません。

## タスクをリスト化する  

## 休憩時間のルールを決める  

## 「やらないこと」のリスト化  


# ポモドーロ・テクニックの基本的な流れ

 1. Todoシートの優先順位の高いものからタスクを選び、25分のタイマーを設定します。

 2. タイマーをスタートし、終了するまで作業します。
タイマーが鳴ったら5分休憩します。これを4ポモドーロ繰り返します  

 3.4ポモドーロ終了したら、15分から30分間の長めの休憩を取ります。これを一日に数回繰り返します。

# まとめ  
> 以上を踏まえると、生産性向上するのでお試しあれ 

# 参考
[https://next.rikunabi.com/journal/20161026_m1/](https://next.rikunabi.com/journal/20161026_m1/)

[https://learn-tern.com/pomodoro/](
https://learn-tern.com/pomodoro/)
親要素でスクロールイベントが発火されない

以下のようなDOM構成、JavaScriptだとして、親要素でスクロールイベントが発火しませんでした。~~でも何故かDocumentオブジェクトで登録したらスクロールイベントが発火しました。その間の要素で発火されない。~~ [^sorry]

結論、そういう仕様です。MDNに書いてありました。

スクロールイベントはバブリングフェーズでは受け取れないため、~~Documentオブジェクト間の要素は無視されます。~~[^sorry] 親要素で無視されます。
どうしても親要素で発火したい、というのであれば `addEventListener` の第3仮引数 `userCapture` にtrueを指定し、キャプチャーフェーズで発火させます。バブリングフェーズやチャプチャーフェーズについてはQiitaで @hosomichi さんが[記事](https://qiita.com/hosomichi/items/49500fea5fdf43f59c58)を書いています。

以下で実際に挙動を確認出来ます。
こちらがスクロールイベント確認用。
https://murashi-sn.github.io/sample-javascript-api/event_propagation/02

こちらが比較のためのクリックイベント確認用。
https://murashi-sn.github.io/sample-javascript-api/event_propagation/01

```html
<div id="parent">
    <div id="child">SCROLL BAR</div>
<div>
```

```javascript
document.querySelector('#child').addEventListener('scroll', function() {
  console.log('child event called.'); // 呼ばれる
});
document.querySelector('#parent').addEventListener('scroll', function() {
  console.log('parrent event called.'); // 呼ばれない
});
document.querySelector('#parent').addEventListener('scroll', function() {
  console.log('parrent event called.'); // これなら呼ばれる
}, true);
document.addEventListener('scroll', function() {
  console.log('document event called.'); // 呼ばれない
});
```

## 参考
* [DOMイベントのキャプチャ/バブリングを整理する 〜 JSおくのほそ道 #017](https://qiita.com/hosomichi/items/49500fea5fdf43f59c58)
* [StackOverflow](https://stackoverflow.com/questions/19656673/why-does-scroll-event-not-bubble)
* [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/API/Element/scroll_event) スクロールイベントについて
* [MDN web docs](https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener) useCapuereについて

[^sorry]: 確認方法が間違えていました。失礼しました。
オートコンプリート　候補が絞られない(autocomplete jQuery UI ajax)

図のように候補が絞られません。すべて出てきます。ご教授いただけませんでしょうか。推測、じゃないの？どんなことでも構いません。よろしくお願いします。

![a無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433444/bbb994bd-e62d-9253-3bf5-c88b48b9fa66.png)

```html:form.html
<div class="col-sm-3 mb-5">
   <input id="検索" type="text" class="form-control" placeholder="検索">
</div>
<script>
$("#検索").autocomplete({
minLength: 1,
source: function (request, response) {
$.ajax({
  url: "{% url  'search_ajax' %}",      
  dataType: "json",
  type: "POST",
  success: function (data) {
                  data=JSON.parse(data);           
                  response($.map(data, function (obj) {              
                  return {
                          label: obj.顧客__姓,
                           value: obj.顧客__姓,
                  };
   }));
   }
</script>
```
【中小企業にプログラミングを】紙の資料をスキャンしてCSVでリストにした名前に一括変更する

**"中小企業にプログラミングを！"
簡単なプログラミングで効率アップ！プログラマでもない私が必要に迫られ業務改善とともにスキルをあげるシリーズ**

# 概要
長年続いている会社では紙での資料が山積みになっていがち。紙の資料は検索性も低いため、探す時間に無駄が多すぎる。外から来た身からすると、この無駄に時間を費やすことが泣ける。けど泣いても解決しないので、なんとか解決したい。よし、電子化だ。電子化はスキャナで読み込めばいいのだが、読み込んだファイルに個別の名前をつけるマウス操作＆コピペがいちいち大変、、、。ということでpythonを使って名前付け作業を楽にしてみた。

# 全体像
1枚ものの図面のPDF化を想定したものになっているので、ファイルはそれぞれ１ページで、ファイル名は"図番\_付加情報\_付加情報.pdf"となるようにしています。

## フォルダ構造
プログラムとファイル名リストのcsvは同じ階層、PDFファイルはpdfsフォルダに入れます
/
┣list.csv
┣rename.py
┗pdfs
　┣20191008000000001.pdf
  ┣20191008000000002.pdf
  ┣20191008000000003.pdf
  ...
  ┗20191008000000999.pdf


## 作業の順番
1. 紙書類をスキャンしてPDF化する
2. スキャンした順序で付けたいファイル名をリスト化する
3. コード実行

![image_filenamer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148842/13f17f95-7c5e-9eec-31a0-5ccd35a3bdd0.png)


# コード

```rename.py
# coding: utf-8

import csv #csvから情報を得るためのライブラリ
import os #ファイル名変更するためのライブラリ
import glob #フォルダの中身を取得するためのライブラリ

# csvファイルの読み込み
f = open('list.csv', 'r', encoding="utf-8-sig")
rows = csv.reader(f)

# PDFファイルの所在の設定と配列化
path = "./pdfs/"
pdfs = list(glob.glob(path + "*.pdf"))
# 名前順(=読み込んだ順)に並び替え
sorted_pdfs = sorted(pdfs) 


# row[0]にはcsvのA列、row[1]にはB列、row[2]にはC列が入ります
# もし各列にデータがあればその情報をファイル名に付けます。
for row, pdf in zip(rows, sorted_pdfs):
	file_title = path
	if row[0] != "":
		file_title += row[0] + '_'
	if row[1] != "":
		file_title += row[1]
	if row[2] != "":
		file_title += '_' + row[2]
	file_title += ".pdf"

	os.rename(pdf, file_title) # 元の名前から新しい名前に付け替える関数
	print(os.path.exists(file_title)) # 正しく付け替えれたらTrueを表示します

f.close()
```

# あとがき
今回私のケースは紙書類が1000枚以上あってので、プログラムを実行するまでの紙のスキャンとリスト化がめっちゃ大変でした。長年続いてきた中小企業って昔ながらのやりかたを継承し続けているので、改善余地が相当あるように見えます。このあたりを効率化できたら作業効率性が相当違うし、昨今の人手不足問題もいくばくか解消できるんじゃないかと思います。今後も記事を書いていきたいと思うので、似たような境遇の人の参考になれば嬉しいです。
マイグレーションファイルの命名規則

#目的
マイグレーションファイルを作成する際に
作成のみでなく閲覧者などにもわかりやすい命名にするため規則などを記載していく

#taskテーブルを作成
`rails g migration CreateTasks name:string content:text`

```ruby:マイグレーションファイル例
class CreateTasks < ActiveRecord::Migration[5.2]
def change
    create_table :tasks do |t|
      t.string :name
      t.text :content
    end
end
```

#taskテーブルにカラムを追加
`rails g migration AddStateToTasks state:string`
`rails g migration add_state_to_tasks state:string`

```ruby:マイグレーションファイル例
class AddStateToTask < ActiveRecord::Migration[5.2]
  def change
    #[形式]add_column(テーブル名,カラム名,データ型)
    add_column :tasks, :state, :string
  end
end
```
add_columnには次のオプションを指定することができる。
・ null:true … NOT NULL制約を削除
・ null:true … NOT NULL制約を追加
・ limit: size … ファイルのサイズに対する制限を設定
・default:[val]… [val]に設定した値をレコード作成じのカラムのデフォルト値とする

#taskテーブルに追加したカラム名を変更
`rails g migration RenameFromStateToTasks`
`rails g migration rename_state_to_tasks`

```ruby:マイグレーションファイル例
class RenameFromStateToTasks < ActiveRecord::Migration[5.2]
  def change
    #[形式]rename_column(テーブル名,変更前のカラム名,変更後のカラム名)
    rename_column :tasks,:state,:status
  end
end
```
#taskテーブルに追加したカラムのデータ型を変更
`rails g migration ChangeStatusOfTasks`
`rails g migration change_datatype_status_of_tasks`

```ruby:マイグレーションファイル例
class ChangeDatatypeStatusOfTasks < ActiveRecord::Migration[5.2]
  def up
    #[形式]change_column(テーブル名,カラム名,データタイプ,オプション)
    change_column :tasks, :status, :integer

    # オプション
    # limit - カラム長の最大数
    # change_column :tasks, :status, :integer, limit: 120

    # default - カラムのデフォルト値を設定。NULLにしたい場合は、nilを指定
    # change_column :tasks, :status, :integer, default: "タイトルがありません"

    # null - null制約を設定。false -> null制約がON。true -> null制約がOFF
    # change_column :tasks, :status, :integer, null: true
  end
end
```
#taskテーブルに追加したカラムにインデックスやユニーク制約の追加
`rails g migration AddIndexStatusToTasks`
`rails g migration add_index_Status_to_tasks`

```ruby:マイグレーションファイル例
class AddIndexStatusToTasks < ActiveRecord::Migration[5.2]
  def change
    add_index  :tasks, :status
   #add_index  :tasks, :status ,unique: true ユニーク制約も付加可能
  end
end
```
#taskテーブルに追加したカラムにNULL制約の追加
`rails g migration ChangeNotNullToTasks`
`rails g migration change_notnull_to_tasks`

```ruby:マイグレーションファイル例
class ChangeNotNullToTasks < ActiveRecord::Migration[5.2]
  def change
    #tasksテーブルのstatusにNOT NULL制約を追加
    change_column_null :tasks, :status, false
  end
end

```
Discord botがエラーを吐いたときにエラーIDを発行して通知する

# 2022年2月4日追記
[修正版](https://qiita.com/jun50/items/9f0bdc9b464f4b4a566b)を公開したので新規の方はそちらへどうぞ

# 作ろうと思ったきっかけ

私のBotはHerokuで運営しているのですが、エラーを吐いたときにいちいち確認するのが面倒なのと、ログが多いのでその中から発掘するのが大変なので作りました。
https://qiita.com/Taku_427_T/items/9caaf59a5fad011b6841
もともとはこれが便利そうなので作ろうと思っただけですが。
ソースの流用は一切してないです。

# 環境

|ソフトウェア|バージョン|
|---|---|
|開発OS|Ubuntu 18.04.3 LTS|
|実行OS|Ubuntu 18.04.3 LTS(Heroku)|
|Python|Python3.7|
|Discord.py|1.2.3|
インストールは割愛します。

# エラーIDをどうするか

エラーIDは絶対に重複させてはいけません。
どれかわからなくなるからですね。
では何を使うか。絶対重複しないIDといえばUUIDですね。
しかし、

1. UUIDを使うのは大袈裟すぎる
2. いちいちimportするまでもない
3. もっと別のいい方法がある

と言う理由により別の方法に。
ではどうするか。別のチャンネルに転送するのだからそのメッセージIDを使えばいいじゃないか、と。
URLも生成できますし。

# ソースコード

というわけでソースコードです

```python:bot.py
@bot.event
async def on_command_error(ctx, error):
    ch = int型のチャンネルID
    embed = discord.Embed(title="エラー情報", description="", color=0xf00)
    embed.add_field(name="エラー発生サーバー名", value=ctx.guild.name, inline=False)
    embed.add_field(name="エラー発生サーバーID", value=ctx.guild.id, inline=False)
    embed.add_field(name="エラー発生ユーザー名", value=ctx.author.name, inline=False)
    embed.add_field(name="エラー発生ユーザーID", value=ctx.author.id, inline=False)
    embed.add_field(name="エラー発生コマンド", value=ctx.message.content, inline=False)
    embed.add_field(name="発生エラー", value=error, inline=False)
    m = await bot.get_channel(ch).send(embed=embed)
    await ctx.send(f"何らかのエラーが発生しました。ごめんなさい。\nこのエラーについて問い合わせるときはこのコードも一緒にお知らせください：{m.id}")
```

# 解説

`on_command_error`でエラーを受信(？)します。
次にembedを生成します。

* サーバー名
* サーバーID
* ユーザー名
* ユーザーID
* 実行コマンド
* 発生したエラーの内容

ですね。
これを`ch`変数で指定したチャンネルに送信します。
エラーが発生したチャンネルにその送信したメッセージIDと一緒にメッセージを送信する、といった感じですね。
エラーIDからエラー情報へ行くには

```
https://discord.com/channels/serverID/channelID/messageID
```
でできます。

コマンドで取得したい場合は

```python:bot.py
@bot.command()
@commands.is_owner()
async def get_error(ctx, error_id):
    await ctx.send(embed = (await bot.get_channel(チャンネルID).fetch_message(error_id)).embeds[0])
```

みたいな感じになります。
[SwiftUI]UIHostingControllerの最小サイズを取得する

SwiftUIをUIKitの世界に連れてくるにはUIHostingControllerを利用し、UIKitのコンポーネントとしてコンテナ化します。
モーダルなどとして利用する場合は、UIHostingControllerをそのまま使えば良いですがコンテナビューとして使いたい時は最小サイズが知りたくなります。
`sizeThatFits`のメソッドが生えているので、そこに対してInt.maxのサイズを渡してあげれば最小をとることができます。

```swift
let hostingController = UIHostingController(rootView: content())
let size = hostingController.sizeThatFits(in: CGSize(width: Int.max, height: Int.max))
```
gitのconfigを適切に設定して悲劇を防ごう ~user編~

# これなんの記事?
と思ったあなたのためにまずは説明を。

あなたは自分のpcでとあるプロジェクトの作業をしようとしています、「githubのこのリポジトリcloneして作業お願いします」と言われたので、ささっと作業してpush。

ふう、今回もスマートに作業を終わらせてしまった・・・と悦に浸っていたのですが次の日会社に出社すると「よお!クラウド!」、「あ、クラウドじゃん!」、「クラウドさんチーッス!」と言い始める同僚社員たち、なぜ誰にも言ったことのない自分のハンドルネームが!?と困惑するあなた、全ては昨日の作業が原因だったのです。

<img width="805" alt="スクリーンショット 2019-10-09 3.16.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236058/c63fb5f0-7bc5-dceb-fc06-3cdfa1bc7caf.png">

なんとgithub上で閲覧できるコミット履歴に自分が個人的に使っているHNが表示されてしまっているではないですか！

# 何が起こったの?
ローカルリポジトリごとにユーザー情報を設定していなかったため、グローバルに登録されたユーザー情報が使用されてしまっていたのです。

gitのコミットにはコミットしたユーザーの情報が含まれることはご存知でしょうか。

`git log` で出力したコミット履歴を見ていくとこんな表記があるはずです。

```
Author: †kuraudo† <kuraudo@sefirosu.com>
```

で、この情報どこから出てきたの?ということなんですが、gitインストールして初回のコミット前にみなさんユーザー情報(ユーザー名&メールアドレス)を登録しているはずです。
↓多分こんなの

```
git config --global user.name †kuraudo†
git config --global user.email kuraudo@sefirosu.com
```

この設定、 `--global` オプションがついているため、各ローカルリポジトリ別にユーザー情報の設定がなければ全てのローカルリポジトリで使用されます。
恐らくクラウドさんことあなたはgitインストール初期にgitの公式を見て言われるがまま自分の好きなユーザーネームと個人で使用しているメールアドレスを入れてしまったのでしょう。

そしてcloneしたてのローカルリポジトリにはuser情報の設定がないため、globalに設定された上記のユーザー情報がそのまま使用されてしまったというわけですね。

ローカルリポジトリ別の設定を確認するには、git管理下のディレクトリに入って `git config --local -l` コマンドで確認できます。

```
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
...(略)
```

こんな感じで色々設定があると思いますが、 `user.name` と `user.email` という設定は存在していないはずです。

# どうしたらいいの?

今回のような悲劇を繰り返さないためにはどうすればいいかというと前述の通りlocalでユーザー情報の設定を追加してあげれば良いわけですね。

```
git config --local user.name kasyuu
git config --local user.email xxx@xxxx.com
```

`git log --local` で確認してちゃんと設定されていればOK 

```
user.name=kasyuu
user.email=xxx@xxxx.com
```

コミットしてpushし直してみましょう。

<img width="757" alt="スクリーンショット 2019-10-09 3.58.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236058/ee0fe5b6-3bf9-492f-a532-72cf419c9c48.png">

ちゃんと自分のユーザー名が表示されましたね。

ちなみにアイコンにgithubのアイコンが表示されていることに気づいた方もいるかもしれませんが、githubやgitlab等大半のリモートリポジトリホスティングサービスでは、ユーザー登録時に使用したユーザー名とメールアドレスがコミットユーザー情報と一致した場合、自動的に登録されているユーザー情報と紐づけてくれます。

そのため、基本的には**使用しているホスティングサービスで使用しているユーザー名とメールアドレスを登録する**のが良いでしょう。

# さいごに
> そのため、基本的には**使用しているホスティングサービスで使用しているユーザー名とメールアドレスを登録する**のが良いでしょう。

正直これが一番言いたかった。
(あまり気にしない方もいるかもしれませんが、登録されていないユーザーの名前がgithub等のコミット履歴に並ぶの気持ち悪くありません?アイコンも表示されないので視覚的にもわかりにくいですし・・・)
Redisの期限切れキーについて

# Redisのexpire設定について
Redisのキーに、有効期限の設定方法。

```
> set test 12345
OK
> EXPIRE test 300
(integer) 1
> ttl test
(integer) 294
```

# Redisの期限切れキーについて
キーの期限切れ削除方法は、受動的方法と能動的方法の2つ。

* キーがアクセスされたタイミングで削除
  キーがアクセスされたタイミングで、タイムアウトを確認する。
* 自動削除
  2度とアクセスされない期限切れキーは、永遠に残ってしまうので以下の手順で削除
  Redisは、以下の操作を1秒間に10回行う。
  1. キーセットから20個のキーをランダムに取得
  2. 期限切れキーを削除
  3. 期限切れキーが25%以上ある場合は、1から繰り返す
  期限切れのキーが25%未満になるまで繰り返されます。

### 気づき
Redisで、`keys *`を実行した時にアイテムカウントが一気に減少したのは、全部のキーにアクセスして残りの25%のものが削除されたからなのか。

# Redisのメモリを使い果たしたときの動作
maxmemory-policyで設定できる。
allkeys-lru : 全部のキーで、参照されていない時間が長いものから削除
noeviction : エラー返却
etc...
composer requireがInstallation failedするけどどうしてもrequireしたいんだ

# Composer requireしたらなんか怒られて失敗した

```
# composer require kalnoy/nestedset
Using version ^5.0 for kalnoy/nestedset
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - illuminate/events v6.2.0 requires php ^7.2 -> your PHP version (7.1.29) does not satisfy that requirement.
    - 省略
    - illuminate/events 6.x-dev requires php ^7.2 -> your PHP version (7.1.29) does not satisfy that requirement.
    - Conclusion: don't install kalnoy/nestedset v5.0.0
    - Conclusion: remove laravel/framework v5.6.38
    - Installation request for kalnoy/nestedset ^5.0 -> satisfiable by kalnoy/nestedset[v5.0.0, v5.x-dev].
    - Conclusion: don't install laravel/framework v5.6.38
    - kalnoy/nestedset v5.x-dev requires illuminate/events ~5.7.0|~5.8.0|^6.0 -> satisfiable by illuminate/events[5.7.17,省略v6.0.4, v6.1.0, v6.2.0].
    - don't install illuminate/events 5.7.17|don't install laravel/framework v5.6.38
    - 省略
    - don't install illuminate/events v5.8.9|don't install laravel/framework v5.6.38
    - Installation request for laravel/framework (locked at v5.6.38, required as 5.6.*) -> satisfiable by laravel/framework[v5.6.38].


Installation failed, reverting ./composer.json to its original content.

```

# 原因
今入れようとしたパッケージ（kalnoy/nestedset）とすでに入っているパッケージ(laravel/framework)がそれぞれ同じパッケージ(Illuminate/events)の違うバージョンに依存してしまっている。
本来なら古いバージョンのものをわざわざ入れるのは良くない（と思う。）が、今回はどうしても使いたいし、今後すでに入っている方(laravel/framework)のパッケージのバージョンをあげた際に解決する可能性もあるので強引に突破する。


# 解決法
このようにバージョン指定にアスタリスクをつけて、依存関係が解決されるバージョンが存在するのを祈る。

```
# composer require kalnoy/nestedset:4.*
```

kalnoy/nestedsetは現時点で5系が最新、4系の最新が4.3.5だったが、4.3.4で入った。
これでもしだめだったら`:3.*`、`:2.*`と順にやっていくしかない。
黒い画面とかよくわかんないしgithubブラウザ操作でpages作りたい

Q. 令和の時代なんですしターミナル使ったほうが早くないですか？
A. せやな。

html+js+cssの前時代的サイトならブラウザ操作のみで作れる
多分ここだけイントラネット黎明期だと思うんですが（名推理）

# 完成品
https://vprjct.github.io/aigis-quiz/
某タワーをディフェンスするゲームのキャラ名をひたすら打ち込んでいくという
令和の時代に許されざる非人道的行為
js素人なのでいろいろ怒られそう

# [できる] リポジトリ作成
普通にgithubでリポジトリ作る。
黒い画面ないとgit initとかいう難しいコマンドは使えないのでInitializeに必ずチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42240/9808f3aa-9d2e-b581-bc22-571288aa5abb.png)
いれないと死ぬ

# [できる] github pages設定
先人が解説してる通りにやる。
index.htmlおいてsettingいじる。
ファイル追加は後述。

# [できる] ブランチ切る
ブランチ選択プルダウンで新規名前つければできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42240/421ff100-f746-505a-f002-659b46f7ce4f.png)

# [できる] ファイル追加 / フォルダ作成
`Create new file` 押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42240/ea6098e8-ff94-a1b4-f3c0-09caed985d8a.png)
こんな感じに/で区切ると経由パスのフォルダも同時に作成してくれる。すごい。
空フォルダを作ることはできないので適当に空ファイル (.gitkeep) おいておく。

# [できる] 素材追加
Upload filesから実行可能
ボタン押したパス直下にファイルが追加されるので注意する

# ファイルリネーム
## [できる] フォルダ下層に移動
フォルダ作成時と同様、rename名に/を入れるとフォルダを作成/移動してくれる。

## [できない] フォルダ上層に移動
**我々に甘えたコマンドは許されていない。**
前進あるのみ。振リ返リマセン勝ツマデハ。

# [できない] フォルダリネーム
**我々に甘えたコマンドは許されていない。**
一度つけたフォルダ名を変えるなどと言語道断である。

# [一応できる] フォルダ削除
我々にそのような甘えたコマンドは許されていない。
……と思いきや、仕様上ファイルの中身をすべて削除すればフォルダも消える。
**たとえ中身が100件、200件あろうとも。**
CloudFront で IPv6対応の APIを作る際の罠

## IPv6なAPIをつくりたいぞ！

APIGateway x Lambda で APIをつくるのは定石だが、IPv6対応させようとした瞬間に悩む。
__そう、APIGatewayが、IPv6対応していないのである！__
仕方がないので、手前にCloudFrontを置いてやるのが、これまた定石。

> APIGatewayの手前のCloudFrontって、エラー時とかタイムアウト時のキャッシュ周りで癖が強いから、ちゃんと設定しないと、ユーザが無限エラーにハマったりで大変だよね、、とかあるけど、それはまた別の話

## 独自ドメインを振りたいが？

さて、CloudFront => APIGateway => Lambda したところで、当然ドメインを振りたいわけだ。
AWSあるある、マネージドサービスにドメイン振る場合はRoute53必須問題。

だが、そんなことは百も承知。
しかも私は賢いので、CNAMEではなく、ALIASレコードで華麗にマネージドサービスに別名をつけるのさ、ふふん。

と思っていたんですけどね、補完候補にCloudFrontのDistが出てこねーんだわ。。
仕方なく、手動で入れるとちゃんと認識する、なんでやねん。
（あと地味にCloudFront側のCNAMEリストにALIASレコードと同じ名前の定義を入れないとダメって初見だと気づかんよね...）

## あとはHTTPS対応かな？

独自ドメインにする場合、ACMに証明書を登録しておかないとCloudFront側の設定が進めなくなって詰む、ガッテム！
しかし、私は賢いので、ACMにちゃんとGeoTrustの証明書をインポートしてあるのさ、ふふん。

と思ってたんですけどね、補完候補にACMで登録したはずの証明書がでてこねーんだわ。。
調べていくと、CloudFrontが参照するACMはバージニアリージョンのACMなんだってさ！へぇ！
ファック！！と殺意を覚えつつも、バージニアのACMに証明書を入れたら、無事認識してめでたしめでたし。

## にしても、CloudFront遅すぎない？

ここまでCloudFrontの設定を変えて更新を繰り返しているのだが、どうにも遅い。
設定をミリ弄って更新を押すと、都度10分〜30分は帰ってこない。
こんな状態でトライ&エラーとかやってられるかという感じだ。
（CNAME/ACMに依存する設定をかえると、30分かかる感じだった）

ちなみに、deploy now みたいなステータスでアクセスすると、変な挙動したり、レスポンスが先祖返りすることがあるが、そういうものみたいなので、この状態での動作を気にしてはいけない。

## IPアドレス問題

もう疲れたので終わりにしたいけど、なんかね、APIGatewayで $context.identity.sourceIp を使ってたんですよ。
__なんとこいつが、CloudFrontのIPアドレスで入ってきて、クライアントのIPが取れねぇw__
ELB挟んだりするのと同じと言われると、なるほど、と思うが...いやいやいや。

で、どうすりゃえーねんというと、 X-Forwarded-For ヘッダーを信用して、APIGateway側のマッピングテンプレートでこいつをLambdaに渡してやれということだ。（カンマ区切りで中継IPが全てはいるので、Lambda側でパースが必要。）
ちなみに、$context.identity.sourceIp は IPv6を受け取れないが、X-Forwarded-For にはIPv6が入る。なるほどね。

## IPv6 Only のエッジを分けておきたい

普通はDual StackのAPIでおわり、、なんだが、用途として特殊で、IPv4とIPv6のエッジを明示的に指定できるようにしておきたかったのだ。

Route53のALIASレコードでAとAAAAを違う名前でつけておけば実現できる、そう思っていた時期が私にもありました。
__これやるとね、Aしか振ってない名前でIPv4/IPv6両方いけるんですよねww（逆も然り）__
色々やったけど、ダメだったので、多分AWSの~~バグ~~仕様なんだと思います。

苦肉の策として、CloudFrontのDistributeを二系統つくって、AのALIASとAAAAのALIASをそれぞれ別に指定してやった。そしたら、期待通りの動き、パーフェクトゲームだ。

## おわりに

こうして、期待するAPI構築が終わり（実際にはCORS問題もあったが、
Serverless Frameworkが優秀すぎて、数分で解決した）、私は帰宅するのであった。

そうそう、「クラウドはIPv6対応万全だ、アプリケーション開発者が怠けてるだけだ」と口を大にしてゆう人を、非開発系のIPv6推進者（笑）の方でよく見かける。

君らは自分でクラウドのIPv6使って開発してから、そういうこと言おうな？
とマジで思う。

IPv6は普及してきたといっても、実際にコンテンツを開発/運用する上で足りてないものが、まだまだたくさんある。みんな、色んな罠や沼で精神汚染されて、苦しむといい。
その苦しみが、IPv6で自在にコンテンツを開発・運用するための糧になる。
というか、今失敗しないと、永久にIPv4の呪縛からは解かれないからな。
テクスチャフィルタリングを簡潔に

## バイリニア

* textureSize = 100x100
* texelColor = sample(x, y)
* uv = (0.221,0.817)

とすると

```
pixelColor 
    = (sample(22, 81) * 0.1 + sample(23, 81) * 0.9) * 0.3
    + (sample(22, 21) * 0.1 + sample(23, 82) * 0.9) * 0.7
```

拡大には強いが縮小に弱い。

## ミップマップ

縮小の際にはミップマップを使う。

切り替わるところが目立つ。

## トライリニア

* mipmapLSize = 100x100
* mipmapMSize = 50x50
* mipmapSSize = 25x25
* texelColor = sample(x, y, mipmap)
* uv = (0.221,0.817)
* depth = 0.8

depth=0の時L,depth=1の時M,depth=2の時Sを使うとすると

```
pixelColor 
    = (
        (sample(22, 81, L) * 0.1 + sample(23, 81, L) * 0.9) * 0.3
        + (sample(22, 21, L) * 0.1 + sample(23, 82, L) * 0.9) * 0.7
    ) * 0.2
    + (
        (sample(22, 81, M) * 0.1 + sample(23, 81, M) * 0.9) * 0.3
        + (sample(22, 21, M) * 0.1 + sample(23, 82, M) * 0.9) * 0.7
    ) * 0.8
```

遠くがぼけるのは改善しない

## 異方性

// 今度書く
Nuxt.jsで同一URLのまま多言語化（i18n）を行う

Nuxt.jsで多言語化を行うには、[nuxt-i18n](https://github.com/nuxt-community/nuxt-i18n)を使用することが一般的かもしれません。
これも使いやすいのですが、言語毎にパスに `/en` が付くなどURLが変わってしまうので、同一URLのまま言語切替ができないか試してみました。

# まずはvue-i18nを導入
今回は[nuxt-i18n](https://github.com/nuxt-community/nuxt-i18n)ではなく、[vue-i18n](https://github.com/kazupon/vue-i18n)を使用します。

```shell
npm install --save vue-i18n
```

# Cookieを使用するためにcookie-universal-nuxtを導入
言語設定をstoreに保存してページ読み込み時に保存した言語を適用したかったのですが、SSR時にstoreの情報を読み込むことはできないので、Cookieに言語設定を保存することにします。
[cookie-universal-nuxt](https://github.com/microcipcip/cookie-universal/tree/master/packages/cookie-universal-nuxt)というモジュールがあるらしく、今回はこれを使ってみます。

[参考] [Nuxt.jsでCookieを使って閲覧したデータを取得する方法](https://qiita.com/sauzar18/items/6eb3fe0218e3cf6badbc)

```shell
npm install --save cookie-universal-nuxt
```

`nuxt.config.js` も更新します。

```nuxt.config.js
modules: [
  ['cookie-universal-nuxt', { parseJSON: false }]
],
```

# 各言語のファイルを作成
各言語のファイルを作成します。
今回は日本語（ja）と英語(en)を想定しています。
ルート直下に `locales` というディレクトリを作成し、 `ja.json` と `en.json` というファイルを置きましょう。

```locales/ja.json
{
  "title": "天使にラブソングを"
}
```

```locales/en.json
{
  "title": "SISTER ACT"
}
```

# pluginsディレクトリ内にvue-i18nの設定を追加
Coockieに保存した言語設定（ `ja` or `en` ）を読み込んで適用します。
設定されていない場合は、日本語が適用されるようにしています。


```plugins/vue-i18n.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';

Vue.use(VueI18n);

export default ({ app }) => {
  const locale = app.$cookies.get('locale') || 'ja';
  app.i18n = new VueI18n({
    locale,
    fallbackLocale: 'ja',
    messages: {
      en: require('~/locales/en.json'),
      ja: require('~/locales/ja.json'),
    }
  });
};
```

# nuxt.config.jsに設定を追加
お約束のやつ。

```nuxt.config.js
plugins: [
  '@/plugins/vue-i18n'
],
```

# 実際に言語切替を実行してみよう
とりあえず、サンプルのページを作りました。

```pages/index.vue
<template lang="pug">
.container
  p {{ $t('title') }}
  v-btn(@click="toggleLocale()") 切り替え
</template>

<script>
export default {
   asyncData({ app }) {
    const locale = app.$cookies.get('locale') || 'ja';
    return {
      isJa: locale === 'ja'
    }
  },
  methods: {
    toggleLocale() {
      this.isJa = !this.isJa;
      const locale = this.isJa ? 'ja' : 'en'
      this.$cookies.set('locale', locale, {
        path: '/',
        maxAge: 60 * 60 * 24 * 365
      });  // localeをCookieに保存
      this.$i18n.locale = locale;           // 言語を切り替え
    }
  }
}
</script>
```

こんな感じで切り替わります↓（URLは変わりません）
![toggle.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/e3405056-d6d7-2281-4cc3-033f98f64cfc.gif)
`this.$cookies.set('locale', locale);` の部分で言語設定をCookieに保存しているので、画面を更新した際も前回設定された言語が適用されます。

以上でやりたいことは達成できました！

# 結論
「SISTER ACT」の邦題を「天使にラブソングを」にしたセンスすごい。
kaggle APIをWindowsで使う

# kaggle APIとは何か

kaggleのあれこれをCLIから操作できるツールです。
pipでインストールできます。

# ブラウザじゃダメなの？

kaggle APIでなきゃ出来ない事は特にないようです。
CLIが好きな人、CLIを使う必要のある人向けっぽいです。

# kaggle APIに出来ること

- コンペ一覧の取得（タイトル、賞金、日程）
- データ一覧の取得（ファイル一覧、データサイズ）
- データのダウンロード

# kaggle APIの準備

#### 1. kaggle APIをinstallする

pipでインストールできます。

```terminal
pip install kaggle
```

#### 2. kaggleサイトでTokenを取得

kaggleの個人アカウントページでkaggle API用のTokenを取得します。アカウントページはユーザー名が「hoge」の場合は以下のようになります。APIの欄でCreate New API Tokenのボタンをクリックするとkaggle.jsonというファイルが落ちてきます。
https://www.kaggle.com/hoge/account
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/332e01ff-40de-6bf2-80ff-6fd26a5b7daa.png)

#### 3. Tokenファイルを所定の場所に置く

Windows10でユーザーアカウントが「hoge」の場合、c:/Users/hoge/.kaggle/ にkaggle.jsonを置けば準備OKです。

#### 4. 使えるか確認する

最初にpipした環境で以下のように実行してhelpが表示されたら正常です。

```terminal:コマンドプロンプト又はAnacondaPrompt
kaggle -h
```

# コンペ一覧を取得する

```terminal:コマンドプロンプト又はAnacondaPrompt
kaggle competitions list
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/0f11e69b-ef56-e436-3849-43392263bd86.png)

# ファイル一覧を取得する

コンペ名を指定してファイル一覧を取得します。titanicの場合は以下になります。

```terminal:コマンドプロンプト又はAnacondaPrompt
kaggle competitions files -c titanic
```

# ファイルを一括ダウンロードする

```terminal:コマンドプロンプト又はAnacondaPrompt
kaggle competitions download -c titanic
```

# Submitする

pred.csvにコメント「test」を添えてSubmitする場合は以下になります。

```terminal:コマンドプロンプト又はAnacondaPrompt
kaggle competitions submit -c titanic -f pred.csv -m test
```

# Submit一覧を取得する

```terminal:コマンドプロンプト又はAnacondaPrompt
kaggle competitions submissions -c titanic
```

エンジョイ！
Angular Connect 2019 - NgTempleteOutlet

# ngTemplateOutlet: The secret to customisation | Stephen Cooper
動画
https://www.youtube.com/watch?v=2SnVxPeJdwE


Sample

https://angular.jp/api/common/NgTemplateOutlet#description

https://github.com/StephenCooper/ngTemplateOutlets

https://stackblitz.com/edit/ngtemplateoutletcontext
なぜGoがWebアプリ開発に適しているのか

# なぜGoがWebアプリ開発に適しているのか

このエントリは[Goプログラミング実践入門](https://www.amazon.co.jp/Go%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E6%A8%99%E6%BA%96%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%A7%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E4%BD%9C%E3%82%8B-impress-gear%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-Sheong-Chang-ebook/dp/B06XKPNVWV)を読んで、5分でもわかるように序章を軽くまとめたものです

## 大規模なWebアプリケーション開発用の言語が必要とする要素
* スケーラビリティ
* モジュール性
* 保守性
* 高速性

Goが上記をカバーしている

### スケーラビリティ

<b>アプリケーションの処理能力を素早く簡単に増強して処理できるリクエストの数を増やすことのできる能力</b>

スケーラビリティの側面

* 垂直方向＝単一のマシンでCPU数を増やして処理能力を向上
    * Goのゴルーチンで効率的に高速に実行
* 水平方向＝マシンの台数を増やして処理能力を向上
    * Go Webアプリケーションの多数のインスタンスの上にプロキシを置く
    * 動的依存性のない静的なバイナリとしてコンパイルされることを利用し、Goが組み込まれていないシステムへ分散

### モジュール性

<b>交換可能なコンポーネントを使って設計することで、機能の追加・削除・変更が容易になり、アプリケーションに対する要求変化に応えやすい</b>

* 関数でインターフェースを引数としてとれるため、新規コード追加でも既存の関数に対してそのインターフェースが要求するメソッドを実装することで、その関数をそのまま使える
* 関数プログラミングのような機能(関数型、値としての関数、クロージャ)が数多く実装されているため、関数から別の関数を生成させることができる

近年話題の「マイクロサービス」中心のアーキテクチャとも親和性が高い

### 保守性

<b>保守が容易なことは、機能改善・修正の際に時間がかからない・デグレを生みにくい</b>

* シンプルな構文
* パッケージシスsテムが柔軟で曖昧さがなく、開発作業効率を上げ、可読性の高いコードを書くためのツールが多い
* ドキュメント作成も楽 ([godoc](https://godoc.org/))
* テスティング ([go test](https://golang.org/pkg/testing/))

### 高速性

C言語の実行速度に近づける思想

* コンパイル型のため、インタプリタ型言語よりは一般的に速い
* ゴルーチンによる並列実行のサポート
iTerm2で自由にタブやペインを行き来するショートカット


一度覚えると、キーボードから手を一切話さずに、タブやペインの分割、移動を自由にできてとっても便利です

# ペイン（Pane）の分割、移動
|キー |動作 |
|:-------|:------------------------------------|
|Cmd + D|	ペインを縦に分割                  |
|Cmd + Shift + D|	ペインを横に分割                  |
|Cmd + ]|	（分割した）次のペインへ移動                  |
|Cmd + [|	（分割した）前のペインへ移動                  |

# タブ(Tab)の追加、移動
|キー |動作 |
|:-------|:------------------------------------|
|Ctrl + Cmd + 1|	ProfilesでShortcut Keyを「Ctrl + Cmd + 1」に設定したタブへ移動                  |
|Ctrl + Cmd + 2|	ProfilesでShortcut Keyを「Ctrl + Cmd + 2」に設定したタブへ移動                  |
|Shift + Cmd + ]|	（現在開いている）次のタブへ移動                  |
|Shift + Cmd + [|	（現在開いている）前のタブへ移動                  |


# おまけ
Profilesで、UTF-8、EUC等よく利用する文字コードをショートカットで登録しておくと便利です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117937/bbc2a6d2-68d9-bfe8-8646-f2699b92e964.png)
サーバサイド初心者がニュートン法の例題を個人的に解こうとした話

いや、待ってめっちゃ数学やん。うふぇぇ苦手なんだよなぁ。。。

ってことでニュートン法についてまずウィキ様から引用します。

[ニュートン法](https://ja.wikipedia.org/wiki/%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%88%E3%83%B3%E6%B3%95)

> 数値解析の分野において、ニュートン法（ニュートンほう、英: Newton's method）またはニュートン・ラフソン法（英: Newton-Raphson method）は、方程式系を数値計算によって解くための反復法による求根アルゴリズムの1つである。対象とする方程式系に対する条件は、領域における微分可能性と2次微分に関する符号だけであり、線型性などは特に要求しない。収束の速さも2次収束なので古くから数値計算で使用されていた。名称はアイザック・ニュートンとジョゼフ・ラフソンに由来する。

やっぱりわかんない。

結局やりたいことは、収束する点を探したいってことと、特定の桁数まで合致するようにif文とfor文を回せってことだと思う。

まず頭の中でどういうアルゴリズムであるべきかを想定する。

xの平方根を求める方法を考える。変数zを使う場合に、10回の試行でどれだけ近づけるかを考える。

一回書いてみっかーヒント見ながら。

```go
package main

import (
	"fmt"
	"math"
)

func Sqrt(x float64) float64 {
	z := float64(1)
	fmt.Println(math.Sqrt(x))
	for i := 0; i < 9; i++{
		z -= (z*z - x) / (2*z)
		}
	return z
}

func main() {
	fmt.Println(Sqrt(2))
}
```

はい答え。。。

10回の試行で小数点以下16桁まで合うのすげぇ。

まあ、そうか偏差的に計算してるし、そらよっていくよね。1000からzを初めて10回試行で2ケタくらいだし。

おもしろいなぁ
Vultr APIを使ったお手軽スナップショット取得

'2023/03/13追記 ここから
VULTR API v1は廃止間近のため、v2版を作成しました。
[Vultr APIを使ったお手軽スナップショット取得 API v2版](https://qiita.com/ataru_mix/items/4116f41b141619a6dd93)
今後はこちらを参照してください。

'2021/10/8追記 ここから
長いことスナップショット無料だったVultrですが、一部のユーザーがバカスカ使って割が合わなくなったようで、'2021/10/以降は \$0.05/GB/month の金額が課金されることになりました。AWSと同額ですね。
自分が使っているインスタンスではスナップショット1本10GB程度なので、この記事のように3本残す設定にすると \$1.5/month 程度の追加支出になります。
'2021/10/8追記 ここまで

個人的お気に入りVPSのVultrは、AWSほど作り込まれてはいませんがAPIによるコントロールも可能で、curlによる呼び出しだけでOSとアプリケーションを指定して仮想マシンを立てたりファイアウォールを設定することも可能です。
以下にAPIのリファレンスがあります。
[Vultr API](https://www.vultr.com/api/)
[Vultr Metadata API](https://www.vultr.com/metadata/)

ここでは、自分がcronに仕掛けて実用しているインスタンスのSSDのスナップショット取得、整理のシェルスクリプトを公開しておきます。curl,jqがインストールされている前提です。

なお、スクリプト中の"YOUR_VULTR_API_PERSONAL_ACCESS_TOKEN"は各自のアクセストークンに置き換えてください。
Vultrの管理画面の右上、アカウント名が表示されている箇所をクリックして出るドロップダウンから「API」を選択して表示されたページに、"Personal Access Token"の項目があります。ここに表示されているのが各自のアクセストークンです。
また、このページ下部には"Access Control"の欄があり、APIを発行できるIPアドレスを制限しています。ここにスクリプトを動かすインスタンスのIPを追加しておきましょう(***重要***)。

## スナップショット取得
```
#!/bin/bash
METADATA='http://169.254.169.254'
API='https://api.vultr.com'
KEY='YOUR_VULTR_API_PERSONAL_ACCESS_TOKEN'

echo '-------------------'
date
SERVERID=$(curl -sS $METADATA/v1.json|jq -r .instanceid)
echo $SERVERID
EPOCH=$(perl -e 'print time();')
echo $EPOCH

SNAPSHOTID=$(curl -sS -H "API-Key: ${KEY}" ${API}/v1/snapshot/create --data "SUBID=${SERVERID}" --data "description=${SERVERID}-${EPOCH}" |jq .)
echo $SNAPSHOTID
curl -sS -H "API-Key: ${KEY}" ${API}/v1/snapshot/list |jq -r '.[]|[.SNAPSHOTID,.description]|@tsv' |grep $SERVERID |sort
```

## スナップショット整理

```
#!/bin/bash
METADATA='http://169.254.169.254'
API='https://api.vultr.com'
KEY='YOUR_VULTR_API_PERSONAL_ACCESS_TOKEN'
SNAP_MAX=3

echo '-------------------'
date
SERVERID=$(curl -sS ${METADATA}/v1.json|jq -r .instanceid)
echo $SERVERID

LIST_REMOVE=$(curl -sS -H "API-Key: ${KEY}" ${API}/v1/snapshot/list \
 |jq -r '.[]|[.description,.SNAPSHOTID]|@tsv'|grep $SERVERID \
 |sort|awk '{print $2}'|head -n-${SNAP_MAX})
echo "[ $LIST_REMOVE ]"
for SNAPID in $LIST_REMOVE; do
  curl -sS -H "API-Key: ${KEY}" ${API}/v1/snapshot/destroy --data "SNAPSHOTID=${SNAPID}"
done
```
シェル変数のSNAP_MAXが残すスナップショットの本数です。
Vultrでは今の所スナップショットは無料ですが、無限に溜め込み続けてサーバーリソースを圧迫するのも悪いので最新の数本以外削除するようにしています。
なお、感覚的に一瞬で終わるAWS EBSのスナップショットなどとは異なり、スナップショットの取得に$6インスタンスの32GB SSDで20~30分くらいかかる様子なので(AWSのスナップショット取得の速さが異常)、スナップショット整理は取得の30分くらい後に走らせたほうが安全でしょう。
サーバサイド初心者がGoの基本構文を個人的に理解しようとした話

A Tour of Goも中盤に差し掛かり基本構文の章に差し掛かりました。

# For文

- 普通のfor文

```go
func main() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)
}
```

- while文的な書き方


```go
func main() {
	sum := 1
	for ; sum < 1000; {
		sum += sum
	}
	fmt.Println(sum)
}
```

ということはもちろんセミコロンを排除できる

```go
func main(){
       sum := 1
       for sum < 1000 {
             sum += sum
       }
       fmt.Println(sum)
}
```

スラっとした綺麗なコード、if文まだ触ってないからあれやけど、` for bool ` もできるのでは？

- 無限ループ

```go
func main(){
       for {
       }
}
```

# if文

- 典型的なif文構築

```go
package main

import (
	"fmt"
	"math"
)

func sqrt(x float64) string {
	if x < 0 {
		return sqrt(-x) + "i"
	}
	return fmt.Sprint(math.Sqrt(x))
}

func main() {
	fmt.Println(sqrt(2), sqrt(-4))
}
```

- 前にステートメントを付けたとき

```go
func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
	    fmt.Println(v)
		return v
	}
	return lim
}
```

このコードを理解するのに時間がかかったくらいにはプログラミング初心者なのかもしれない（）
最初の ` v := math.Pow(x,n); でステートメントを追加してvにxをn乗したものを代入して、
if v < limならこのメソッドは戻り値にvを返す。違うならlimをっていう形ですねー。

マジでちょっと悩んだのが悔しい。

- else文

```go
 func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	} else {
		fmt.Printf("%g >= %g\n", v, lim)
	}
	return lim
}
```
elseを入れる場合もこのケースでのvなどのif文で生成した変数は、スコープ内として扱える。

ほう。。。なるほど。。。

割と簡単なケースが多くて割と安心したっていうのが正直なところっていう感じ。

# Switch文

```go

func main() {
	fmt.Println("When's Saturday?")
	today := time.Now().Weekday()
	fmt.Println(today)
	switch time.Saturday {
	case today + 0:
		fmt.Println("Today.")
	case today + 1:
		fmt.Println("Tomorrow.")
	case today + 2:
		fmt.Println("In two days.")
	default:
		fmt.Println("Too far away.")
	}
}
```

一般的な記法と同じでif else構文を短縮したもの。便利でいいなーってサンプルコードを読んでて思ったのは、time.Now().Weekday()って呼ぶだけで、当日の曜日がわかるのは正直激アツ。

- switch trueも可

```go
func main() {
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
	}
}
```

なるほど。簡単

# defer
これやばい、意味わかんね。やばい。

```go
func main() {
	x := 1
	defer fmt.Println(x)
	x = 2
	fmt.Println("hello") 
}

//出力結果
//hello
//1

```

deferはその呼び出し元のメソッドがリターンすると呼び出されるもの。参照はトップダウンで終わるが、呼び出しが実行後にくるって、なるほど。参照が先にされるのが少し自分的にははてながつくが、まぁそういうもんだろうと一旦流す。

- Last-in-First-Out

```go

func main() {
	fmt.Println("counting")

	for i := 0; i < 10; i++ {
		defer fmt.Println(i)
	}

	fmt.Println("done")
}
```

この場合はLiFOの原理によって9から逆順になる。最後に入れたものが最初に出てきて、最初に準備してた人が最後に出てくる。逆リハ。的な。その。的な？
JavaとJavaScriptの違い(平均の求め方)

単純ではありますがこちらもアウトプット

#Java

```java

import java.util.*;
public class Test12{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int sum = 0; //合計を保存するための変数
int a=0;
while (true) {
    System.out.println("数値を繰り返し入力して下さい(0で合計と平均をだして終了)"); //メッセージに終了条件を追加
    int num = scan.nextInt();
    if (num == 0) {
        break;
    } else {
        sum += num;
        a++;//おわるまで加算していく
        }
    }
//System.out.println("合計は"+sum);//
System.out.println("平均は"+sum/a);
 }
}
```

一例です。


#JavaScript

```Jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>jsave</title>
</head>
<body>
  <h1>平均の計算</h1>
  <input type="number" id="num" value="" placeholder="数値を入力"/>
  <button onclick="add()">Add</button>
  <button onclick="btCalc()">Calc!</button>
  <div id="msg"></div>
<script>
var nums=[];
var str="";
var eleNum=document.getElementById("num");
var eleMsg=document.getElementById("msg");
function add(){
//intに変換だがJavaと違いIntegerではない

  var num=parseInt(eleNum.value);
  nums.push(num);
  eleMsg.textContent=num+"を配列に追加";
}
function btCalc(){
	var sum=0;
	for(var i=0;i<nums.length;i++){
	str +=nums[i]+(i==nums.length-1?"":",");
    sum +=nums[i];
  }
	document.getElementById("data").textContent=str;
	var msg='[{${nums.join(",")}]の平均は${sum/nums.length}です。';
    eleMsg.textContent=msg;
}
</script>
</body>
</html>
```
とりあえずvarはブロックスコープ(let,const)に変えるべきなんでしょうな。

躓いた所で言えば

```jsp

<script>
'use strict';
window.onload=function(){
  //dom取得
  let ele=document.getElementById("bt");
  let result=document.getElementById("result");
  //特定のイベントが対象に配信されるたびに呼び出される関数を設定します。 
  ele.addEventListener("click",function(){
    result.textContent="Clicked!";
  });
  ele.addEventListener("click",function(){
    window.alert("Clicked!!!");
  });
};
</script>
```
のようにHTMLを読み込んだ後にメソッドを実行？とか。。意味や意義を考えてたら理解が難しかったですね。。
UE4でオープンソースのプロファイラーOptickを使う

# Optickとは

Optickはゲーム用の超軽量C ++プロファイラーです。

[Optick 公式ページ](https://optick.dev/)
[Optick Githubリンク](https://github.com/bombomby/optick)


公式チュートリアル動画
[![Optick公式チュートリアル動画](http://img.youtube.com/vi/YOUTUBE_VIDEO_ID_HERE/0.jpg)](https://www.youtube.com/watch?v=p57TV5342fo)

※UE4.23なら公式の新プロファイラがあるのでそれ以前のバージョンで導入するほうが良いかもしれません

# UE4でOptickを導入する


## GithubのページからOptickPluginをDLします

[UE4-Optick-Plugin公式導入ページ](https://github.com/bombomby/optick/wiki/UE4-Optick-Plugin)
コチラのページで足りない事は上記の公式ドキュメントを参照してください

```:note
DLできるバージョンはUE4.23と記載されていますが、UE4.20でも動作を確認しております。
使うUE4のバージョンによって差異があるかもしれませんが未検証となります
```


画像を参考にUE4のPluginをダウンロードします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66029/10f44f68-42d6-3843-4802-a49a9a334e75.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66029/f6796e56-e5bf-2dc5-b948-85fcdd3d9c91.png)

```:プラグインの配置箇所
!{プロジェクトのパス}/Plugins/Performance/OptickPlugin
```

上記のパスに先程ダウンロードして解凍したフォルダを配置します。
解凍してきたバージョンでは4.23のバイナリがありますが違うバージョンのUE4を使っている場合はVisualStudioが必要になります
後は通常通りにビルドするだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66029/97f47f13-c080-11bb-307f-020115ce22a2.png)

プラグインで指定されているUE4のバージョンと現在使用しているUE4のバージョンが違っているのでロードするか警告が出ます。
upluginを編集する事で回避する事が出来ます

```json-doc:OptickPlugin\OptickPlugin.uplugin
{
	// 以下略
	"EngineVersion": "4.20.0", // ここのバージョンを自分の使うUE4のバージョンに変えてください
```

# Optickを使ってみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66029/4b723f9d-10dd-0b14-5df0-1ef022d491fb.png)

プラグインを有効にするとOptickボタンが追加されます。
コチラを押すとOptickプロファイラーが起動します。
Optickプロファイラーでの再生ボタンと停止ボタンを押している間プロファイルを行います。
![optick.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66029/35b74d71-cfdb-c1ef-b8b9-a176b2b04470.gif)

上部のウインドウで確認したいフレームを選択します。
そうするとThreadsウインドウに処理がノード上に表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66029/9a51cb7c-eeb1-2c62-fe3d-41402e1b057b.png)
【JavaScript】数値から文字列に変換する

JavaScript を勉強することになったのでとりあえず FizzBuzz を書いてみることにしました。
FizzBuzz 関数内において、引数として受け取った値を Number 型から String 型に変換する必要が出てきた際に詰まりました。
そこで、Number 型から String 型への変換方法を調べてみた結果、色々見つかったので残しておくことにしました。

#結論を先に書いておく。
Number 型の値をただ文字列に変換したいだけならば、`String()` で変換するのが一番いいと思う。

#String(Number)
ただ単純に Number 型のオブジェクト(以下、Number)を String 型のオブジェクトに変換するみたいです。
恐らくこれが最もオーソドックスな方法なのかな？と感じます。

```javascript:NumToStr1.js
var num = 100;
var s = String(num); //=> "100" 
```

#Number.toString(n)
このメソッドは Number を **n 進数に変換した文字列**を返すみたいです。
そのため、Number が 10 進数ならば、引数 n に 10 を指定すればそのまま Number を String 型に変換することができます。
また、引数に何も指定しない場合は `n = 10` として Number が変換されます。

```javascript:NumToStr2.js
var num = 255;
var s1 = num.toString(10); //=> "255"
var s2 = num.toString(16); //=> "ff"
var s3 = num.toString(32); //=> "7v"
var s4 = num.toString(); //=> "255"
```

#Number.toFixed(n)
このメソッドは Number の**小数点以下の桁数を n 桁にした文字列**を返すみたいです。 
そのため、文字列に変換したい Number が整数ならば、引数に 0 を指定すればそのまま文字列に変換することができます。

```javascript:NumToStr3.js
var num = 3.141592;
var s1 = num.toFixed(0); //=> "3"
var s2 = num.toFixed(6); //=> "3.141592"
var s3 = num.toFixed(10); //=> "3.1415920000"
```

#その他
**\+ 演算子を文字列連結演算子として解釈させる**ことで、文字列に変換する方法もあるみたいです。

```javascript:NumToStr4.js
var num = 100;
var s = num + ""; //=> "100"
```

#参考
[SOFTELメモ](https://www.softel.co.jp/blogs/tech/archives/5524)
[MDN web docs mozilla : Number.prototype.toString()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/toString)
[MDN web docs mozilla : Number.prototype.toFixed()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed)

#まとめ
Number をただ文字列に変換したいだけならば、`String()` で変換するのが一番よさそう。
値を n 進数に変換し、さらに文字列として扱いたいなら、 `Number.toString()`。
`Number.toFixed()`はきっとピンポイントで使うときがあるんだろう（よくわからないけど）。
npmのパッケージサイズのビジュアライザー

npmのパッケージがどれぐらいのサイズ使ってるのか見ようと思ったときに、思ったよりもたくさんのビジュアライザがありました。


# webツール
###  bundlephobia
https://bundlephobia.com/

見やすくてきれい。とりあえず見たいのであればこれで十分。

<img width="645" alt="スクリーンショット 2019-10-08 14.20.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/8fbbdafb-ab4d-5aea-fda7-0b88260acc42.png">



### packagephobia
https://packagephobia.now.sh/result?p=obniz

bundlephobiaとほぼ同じだが、依存関係の容量表示がない分、ちょっと物足りない。惜しい。

<img width="643" alt="スクリーンショット 2019-10-08 14.21.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/95d69e5a-807a-f51e-9986-f772f38888d2.png">



### npm download size
https://arve0.github.io/npm-download-size/

テキストで見たいんだ！という硬派ならこちら。必要な情報はきちんと書いてあってシンプル。

<img width="643" alt="スクリーンショット 2019-10-08 14.18.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/6c99030f-11f6-8c23-c981-0ccccf40e924.png">


# コマンドラインツール

### webpack-bundle-analyzer 
https://www.npmjs.com/package/webpack-bundle-analyzer
webpack時についでにビジュアライザのHTMLを作ってくれる。パッケージを作る人向け
しっかりとわかりやすく表示してくれるが、使うのが少々手間。Webpackを使ってないと更に難しい。

<img width="657" alt="スクリーンショット 2019-10-08 14.41.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/d996217f-9a7e-50e4-41f6-cfa25e56ee45.png">


### package-size 
https://github.com/egoist/package-size

複数パッケージを入れるとどのぐらいの容量になるかな　がわかる。
これからどんなパッケージを使おうかなと検討するときに便利。パッケージを使う人向け。

<img width="788" alt="スクリーンショット 2019-10-08 14.36.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/439e12a2-7dec-4ce6-8b5c-251099e201b5.png">

### cost-of-modules
https://www.npmjs.com/package/cost-of-modules
プロジェクトで現在使われているパッケージの容量がわかる。パッケージを使う人向け。

<img width="879" alt="スクリーンショット 2019-10-08 14.34.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/b6bb6f72-9d1b-2e1f-9731-e042bc4c8e36.png">
AUTO INCREMENT

[前回](https://qiita.com/youth_case/items/bd8cb87d2bda02a4b722) でMySQLを復活させられたものの、アプリ経由からデータを一行しか入れられなくなってしまいました。
原因はPRIMARY KEYとして設定していた採番カラムに「AUTO INCREMENT」を設定していなかったから。
カラムを設定する際、この「AUTO INCREMENT」を理解していなかった為、このようなミスが出たと思い、備忘録兼ノートとしてこの記事を作成しました。

#AUTO INCREMENTとは？
AUTO INCREMENTは、データを追加した際にカラムに対して現在格納されている最大の数値に 1 を追加した数値を自動で格納することが出来る機能です。採番や連番など連続した数値を自動で格納させたい時に用いられます。


![phpmyadmin id.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506986/afc87f02-c313-a204-e0ff-136628b1fc45.png)
phpmyadminでは、上図のように「A I」のチェックボックスにチェックを入れることで、そのカラムにAUTO INCREMENTを設定することが出来ます。

#書式
以下の書式で設定することが出来ます。
```CREATE TABLE db_name.tbl_name
  (col_name data_type AUTO_INCREMENT, ...)```

#制約
1.一つのテーブルにつき、AUTO INCREMENTを設定できるカラムは一つ。
2.AUTO INCREMENTを設定したカラムはインデックスを設定する必要がある。
3.AUTO INCREMENTを設定したカラムにDEFAULT制約を設定することは出来ない。
4.AUTO INCREMENTは正の数値を格納した場合のみ動く

#まとめ
とりあえず簡単にまとめました。
今後得たことや気づいた点などがありましたら、追記致します。

#参考サイト
[AUTO_INCREMENTを設定する(連続した数値を自動でカラムに格納する) | MySQLの使い方] (https://www.dbonline.jp/mysql/table/index7.html )
PoWにおけるマイニングのプログラムを作ってみた

# はじめに
こんにちは。ブロックチェーン技術関連の記事になります。
この記事では、コンセンサスアルゴリズムであるPoWにおけるマイニングのプログラムについて書いていきます。
ブロックチェーン技術の詳しい内容についてはこちらの[「ブロックチェーン技術及び関連技術（ブロックチェーン実装あり）」](https://qiita.com/michimichix521/items/1485f05a45a37d7ffe08)の記事を参照してください。

よろしくお願いします。


# 環境

- Windows 10 home
- Python 3.7.3


# プログラム

```mining.py
import hashlib
import random
import string

class Mining():
	def __init__(self,difficulty):
		self.data = self.calcRandomText(10) #データ
		self.difficulty = difficulty #求める規定のハッシュ値の難易度(何文字か)
		self.nonce = 0 #ナンス
		self.answerText = self.calcRandomHexDigitsText(self.difficulty) #求める規定のハッシュ値を算出
		self.nonceDataText = self.calcNonceDataText() #データとナンス値を合わせる
		self.hashText = self.calcHash(self.nonceDataText) #ハッシュ値を算出する

		self.miningLoop() #マイニング開始

	def calcRandomText(self,num): #ランダムな文字列を返す
		_randTextList = [random.choice(string.ascii_letters + string.digits) for i in range(num)]
		return "".join(_randTextList)

	def calcRandomHexDigitsText(self,num): #16進数のランダムな文字列を返す
		_randHexDigitsTextList = [random.choice(string.hexdigits) for i in range(num)]
		return "".join(_randHexDigitsTextList)

	def calcNonceDataText(self): #データのナンス値を合わせる
		return self.data + str(self.nonce)

	def calcHash(self,text): #ハッシュ値を算出する
		return hashlib.sha256(text.encode("utf-8")).hexdigest()

	def miningLoop(self): #マイニングのメソッド
		while self.hashText[-1*self.difficulty:] != self.answerText.lower():
			print("マイニング中  試行回数:" + str(self.nonce+1) + "  求める規定のハッシュ値:"+ self.answerText.lower() + "  算出ハッシュ値:" + self.hashText[-1*self.difficulty:])
			self.nonce += 1 #ナンス値に1を加算していく
			self.nonceDataText = self.calcNonceDataText() #データとナンス値を合わせる
			self.hashText = self.calcHash(self.nonceDataText) #ハッシュ値を算出する
		print("マイニング中  試行回数:" + str(self.nonce+1) + "  求める規定のハッシュ値:"+ self.answerText.lower() + "  算出ハッシュ値:" + self.hashText[-1*self.difficulty:] + "\n")

		print("マイニング成功!" + "  データ:" + self.data + "  ナンス値:" + str(self.nonce))
		print("マイニングに成功したハッシュ値:" + self.calcHash(self.data + str(self.nonce)))

def main():
	difficulty = 3 #求める規定のハッシュ値の難易度(何文字か)
	mining = Mining(difficulty) #インスタンスの生成

if __name__ == "__main__":
	main()

```

マイニングを成功させるには、**規定のハッシュ値を算出するためにナンスの計算をし続けます**。

このプログラムでは、既定のハッシュ値というのはメイン関数にある`difficulty`の値によって決まる特定の値と算出されたハッシュ値の末の値が一致しているハッシュ値のことです。

ハッシュ値から入力データを予測することは困難なので、規定のハッシュ値を算出できるまで、ハッシュ関数にいろんなデータを突っ込みます。そこでいろんなデータにするために使うものがナンスです。
ナンスの使い方としては、ナンスに1を加算しては、ナンスをデータに足して、ハッシュ関数に突っ込むといった感じです。
これを繰り返し、規定のハッシュ値を算出していきます。

ぜひ`difficulty`の値を変えてみて、マイニングの試行がどのくらいの間隔を生み出すのか試してみてください。

これがプルーフオブワーク！仕事量の証明です！
ここまで読んでいただき、ありがとうございました。