OmniAICreator/Qiita-1.07M huggingface dataset:
ブラックジャックの親のバーストの確率をセル関数だけで計算する

# はじめに
ブラックジャックの親のバーストの確率を表計算ソフトのセル関数のみで計算してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/3dfb7f32-64bb-6e2d-de39-316282281445.png)

E3セルで親のオープンカードを選択することが出来て、そのオープンカードの最終形のそれぞれの確率を動的計算します。
サンプルの図では、親のオープンカードが２の時、親がバーストする確率は35.4%ということになります

表計算ソフトの結果はこちらの[Googleスプレッドシート](https://docs.google.com/spreadsheets/d/1swgfZ2xcTfdVxonY_OyPao0dmSsLl5Yrpd-60Y6IF48/)で公開しています。
ただし、クリックしても閲覧しかできませんので、中身をいじったり確認したい方は、[Googleスプレッドシート]のメニューの[ファイル]から[ダウンロード]を選択し、[Microsoft Excel形式]でダウンロードしてください。
Excelソフトをお持ちでない方は、再度自身のアカウントの[Google Drive]にアップロードすれば、[Googleスプレッドシート]で開くことが出来るのではないかと思います。

# ルール
ブラックジャックの細かいルールは他に譲るとして、親は以下のルールに従って、カードを引きます。
まずは1枚を表にしてカードを配り、後は合計が16以下の場合は17以上になるまで無条件でカードを引き続けます。（その時、10,J,Q,Kはすべて10で計算します。Aは11として計算し22以上になってしまった場合は1として計算します）
合計の値が17~21の時は、子供のカードの合計と比較し、大きい方を勝ちとします。
値が同じ場合は引分けとします。
22以上となった場合は、バーストと呼ばれ、子がバーストしていない場合は、親の負けとなります。

# 計算方法
ハードハンド[^1]とソフトハンド[^2]それぞれに確率を計算します。
例えば、ハードハンドの14の確率は以下の確率の合計で計算します。
オープンカードが4の確率 × 10のカードを引く確率 ＋
オープンカードが5の確率 × 9のカードを引く確率 ＋
･･･ 省略 ･･･
オープンカードが9の確率 × 5のカードを引く確率 ＋
オープンカードが10の確率 × 4のカードを引く確率
＋
ハードハンドの4の確率 × 10のカードを引く確率 ＋
ハードハンドの5の確率 × 9のカードを引く確率 ＋
･･･ 省略 ･･･
ハードハンドの12の確率 × 2のカードを引く確率 ＋
ハードハンドの13の確率 × 1のカードを引く確率 
＋
ソフトハンドの14の確率 × 10のカードを引く確率 ＋
ソフトハンドの15の確率 × 9のカードを引く確率 ＋
ソフトハンドの16の確率 × 8のカードを引く確率

ただし、計算過程において、すでに引いてしまったカードの出現率の減少は考慮していません。
例えばAを立て続けに3枚引いてソフトハンドの13になっていても、次にAを引く確率はかわらず約7.7%(4/52)で計算しています。

2021.3.20 追記
[こちら](https://qiita.com/takahasinaoki/items/f92b4cc3d41ac22a7ae3)の記事で使用済みカードの出現率の減少を考慮した確率を計算してみましたので、興味のある方はご覧ください。

[^1]: ハードハンド：Aを含まない　または Aを1として計算した手
[^2]: ソフトハンド：Aを11として計算した手(10を引いてもバーストしない)

# 計算結果
| 初手 | 初手確率 | 17    | 18    | 19    | 20    | 21    | BJ    | BS    |
| ---- | -------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- |
| A    | 7.7%     | 13.1% | 13.1% | 13.1% | 13.1% | 5.4%  | 30.8% | 11.5% |
| 2    | 7.7%     | 14.0% | 13.5% | 13.0% | 12.4% | 11.8% | 0.0%  | 35.4% |
| 3    | 7.7%     | 13.5% | 13.0% | 12.6% | 12.0% | 11.5% | 0.0%  | 37.4% |
| 4    | 7.7%     | 13.0% | 12.6% | 12.1% | 11.6% | 11.1% | 0.0%  | 39.4% |
| 5    | 7.7%     | 12.2% | 12.2% | 11.8% | 11.3% | 10.8% | 0.0%  | 41.6% |
| 6    | 7.7%     | 16.5% | 10.6% | 10.6% | 10.2% | 9.7%  | 0.0%  | 42.3% |
| 7    | 7.7%     | 36.9% | 13.8% | 7.9%  | 7.9%  | 7.4%  | 0.0%  | 26.2% |
| 8    | 7.7%     | 12.9% | 35.9% | 12.9% | 6.9%  | 6.9%  | 0.0%  | 24.5% |
| 9    | 7.7%     | 12.0% | 12.0% | 35.1% | 12.0% | 6.1%  | 0.0%  | 22.8% |
| 10   | 30.8%    | 11.1% | 11.1% | 11.1% | 34.2% | 3.5%  | 7.7%  | 21.2% |
| 平均 | 100.0%   | 14.5% | 13.9% | 13.3% | 18.0% | 7.3%  | 4.7%  | 28.2% |

# 関連記事
https://qiita.com/takahasinaoki/items/094da1dd64c6273502dd

https://qiita.com/takahasinaoki/items/f92b4cc3d41ac22a7ae3

https://qiita.com/takahasinaoki/items/a3e023ede0545582cf52
【Vue.js】Vue Router導入

# Vue Routerとは
webページのルーティングを実装してくれる [Vue.js 公式](https://router.vuejs.org/ja/) のプラグイン

# 導入

Vue CLI を使用しているので、以下コマンド

```
vue add router
```

## 質問がくる
### 質問1
Y

```
There are uncommitted changes in the current repository, it's recommended to commit or stash them first.
```


### 質問2

Y（historyモードを選択する）
https://qiita.com/kozzzz/items/af9ad63fa70d4724cc2a

```
Use history mode for router? (Requires proper server setup for index fallback 
in production) (Y/n) 
```


正常に起動した

```
✔  Successfully invoked generator for plugin: @vue/cli-plugin-router
```
標準入力で入力された高さと長さが分かる図形を二次元配列にする

#今回、例に出す図形
今回、例として出す入力は、

```python
例１(文字列の場合)
4 7
O O O X O O O
O O X X X O O
O X X X X X O
X X X X X X X

例２(数字列の場合)
4 7
0 0 0 1 0 0 0
0 0 1 1 1 0 0
0 1 1 1 1 1 0
1 1 1 1 1 1 1

```

#文字列の場合

```python
h ,w = [int(x) for x in input().split()]
l = [input().split() for _ in range(h)]
print(l)
```

#数列の場合

```python
h ,w = [int(x) for x in input().split()]
l = [[int(x) for x in input().split()] for _ in range(h)]
print(l)
```

#全ての結果

```python
#結果(文字列の結果)
[['O', 'O', 'O', 'X', 'O', 'O', 'O'],
 ['O', 'O', 'X', 'X', 'X', 'O', 'O'],
 ['O', 'X', 'X', 'X', 'X', 'X', 'O'],
 ['X', 'X', 'X', 'X', 'X', 'X', 'X']]
#結果(数列の場合)
[[0, 0, 0, 1, 0, 0, 0],
 [0, 0, 1, 1, 1, 0, 0],
 [0, 1, 1, 1, 1, 1, 0],
 [1, 1, 1, 1, 1, 1, 1]]
```

#終わりに
初めてQiitaで記事を試しに書いてみました。まだPython3の経験が3ヶ月なので、これから暇つぶしに書いていこうと思います。
【Rails】ルーティングを名前空間でグループ分けしている場合のform_withの記法【Ruby】

# はじめに
ヘルパーメソッドのform_withを使用して入力フォームを作ろうとしていたところ、NoMethodErrorが出てしまい詰まっていました。
![スクリーンショット 2021-03-05 21.50.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/937972/aa7dbb0b-96be-b8dc-2c34-2675417beffc.png)


# 結論
`route.rb`においてルーティングを名前空間`shops`でグループ分けしていたにもかかわらず、`shops`をform_withの引数に渡していなかった。

# コード
```Ruby:route.rb
namespace :shops do
    resources :posts  
---中略---
end
```

```Ruby:shops/posts_controller.rb
class Shops::PostsController < ApplicationController
  --- 中略 ---
  def new
    @post = Post.new
  end
  --- 中略 ---
end

```

```ERB:shops/post/new.html.erb
<%= form_with model:[:shops,@post], local: true do |f| %>
      --- 中略 ---
    <div>
      <%= f.submit "送信"%>
    </div>
<% end %>
 ```

resourcesをネストしているときに親モデルを引数に渡すのと同じ感覚です。


# 参考
https://techracho.bpsinc.jp/ohno/2019_12_10/84349
https://railsdoc.com/page/form_with
Linux sedコマンド メモ

# 目的

- 特定の文字列の置換

# s///g とは何か

- s/A/B/g は A という文字を B という文字に置換してね！という意味
- s は置換をしてね！という意味
- g はマッチしたとこ全部置換してね！という意味

■ サンプルファイル

```sample.txt
a,b,c
d,e,f
g,h,i
j,k,l
```

### すべてのコンマを*に置換

```
$ sed 's/,/*/g' sample.txt
a*b*c
d*e*f
g*h*i
j*k*l
```

※ s///g の最後の g がないと、各行の最初にマッチした文字のみ置換する

```
$ sed 's/,/*/' sample.txt
a*b,c
d*e,f
g*h,i
j*k,l
```

### 2行目だけコンマを*に置換

★ 行数を s の前に書く

```
$ sed '2s/,/*/g' sample.txt
a,b,c
d*e*f
g,h,i
j,k,l
```

### 1行目のコンマを*に置換、3行目のコンマを@に置換

★ オプション e は複数の置換をしたいとき使う

```
$ sed -e '1s/,/*/g' -e  '3s/,/@/g' sample.txt
a*b*c
d,e,f
g@h@i
j,k,l
```

### 2行目から4行目のコンマを*に置換

★連続している行なら`2,4s`のように書く

```
$ sed '2,4s/,/*/g' sample.txt
a,b,c
d*e*f
g*h*i
j*k*l
```

# コマンドをスクリプトに書いておく方法

※ コンマをすべて*に置換してね！というコマンドを適当なファイルに書いておく

```mysed.txt
s/,/*/g
```

★ オプション f で上記のファイルを読み込み

```
$ sed -f mysed.txt sample.txt
a*b*c
d*e*f
g*h*i
j*k*l
```
【Swift】MVVMとは？？でモヤモヤしてる人向けの図解付き解説

##前提
ある程度調べていてアーキテクチャという言葉の意味くらいならわかる
RxSwiftを自分なりに調べていて読めはする

##MVVM
まず、アプリの使われ方、あり方について考えてみる。
アプリを使うのはユーザーで、ユーザーはアプリを開き、
つまり画面を開き、**操作**を行う。
この**操作**に対して、ViewModelやModelのロジックが働き、
Viewはそれらのロジックの結果を画面に反映する。

このように、何かのイベントに対して何かのロジックが働き、結果を反映する。
その流れの中で、表示非表示や変形、バリデーション、イベントに対するロジックなど
役割ごとに分け、責務の切り分けをするのがアーキテクチャであり、MVVMである。

###図解
![スクリーンショット 2021-03-05 22.23.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585922/6809332b-ff1d-971d-43fd-0e0c758ceaf2.png)

###View(UIロジック)
言うまでもなく、表示を担当する。
この部分は、ユーザーインターフェース層とも言われ、
ユーザーの目に触れる部分を担当している。
ViewControllerとViewがそれである。

Storyboardと連携し、UIパーツの表示。(Viewの責務)
ユーザーからのタップ、入力イベントなどの操作をViewModelに送信し、
その結果がViewModelから流れてきたらUIコンポーネントや表示ロジックに反映させる。

###ViewModel(プレゼンテーションロジック)
View(ViewController)から送られてくるイベントや値の加工をするところ
入力イベントであればテキストを受け取り、文字数制限などの
モデルに書かれたバリデーションロジック関数を呼び出して
その結果をView(ViewController)に返す。

###Model(ビジネスロジック)
View(ViewController)、ViewModelが担当する以外の役割を担当する。
バリデーションロジックやAPIに関するEntity、Repository、
シングルトンなどのManagerなど、細かい責務がModelに切り出される。


##おわりに
実務で新規開発をして、ふわっとMVVMがわかったので備忘録として。
間違っている点があればコメントしていただけると幸いです。
PHPの型宣言は暗黙の型変換を行う

PHPはPOST送信される値を全て文字列(Stirng型)として受け取ります。
そのため、下記のような関数を実行する場合、都度int型にキャストする必要があると思っていました。

```PHP
function plusOne(int $num)
{
   return $num + 1;
}
```


```PHP
$num = $_POST['num'];//"1"が送られてきたとする
$res = plusOne( (int)$num );

var_dump($res);//2が表示される
```

ただ実際にはキャストをしなくても型エラーを吐きません。


```PHP
$num = $_POST['num'];//"1"が送られてきたとする
$res = plusOne( $num );

var_dump($res);//エラーにならない
```

なぜかと思ったのですが、どうやらPHPの型宣言は可能な限り暗黙の型変換を行うためにこういったことが起きるようです。
つまり、上記のコードはString型の"1"をint型の1に変換してplusOne()関数を実行しています。

個人的にはラクで良いやと思うのですが、これでは型宣言を行う意味が少しぼやけてしまう気もします。
もっとカタい言語の経験がある人からしたら「なんじゃこりゃ」という仕様かもしれません。
そういった方はdeclare文でstrictモードを有効にしましょう。
そうすれば厳密な型宣言が可能になります。

```PHP
<?php
declare(strict_types=1);
```

おまけ
実際には数字を全てint型に変換するラッパー関数を噛ませるのが良さそうですね。

```PHP
    function exePlusOne(int $num)
    {
        return $num + 1;
    }
    
    function plusOne($num)
    {
        if(preg_match("/\A[0-9]+\z/",$num) !== 1) return 0;
        return exePlusOne((int)$num);
    }
    
    var_dump(plusOne('1'));
```

以上
Flutter2/FlutterEngageの10の要点の動画を和訳してみる

---
# :book: Flutterの記事を整理し本にしました :book:
https://zenn.dev/kazutxt/books/flutter_practice_introduction

* <font color="red"><b>本稿の記事を含む様々な記事を体系的に整理し本にまとめました</b></font>
* 今後はこちらを最新化するため、<font color="red"><b>最新情報はこちらをご確認くださ</b>い</font>
* 10万文字を超える超大作になっています(笑)

---

# 3/6 追記
* 本編をしっかり整理したので、こちらのほうが良いかもしれません
* [Flutter2を発表したFlutterEngageの基調講演の覚書](https://qiita.com/kazutxt/items/3455df326903e3a9f292)

# 概要
* 3/3のFlutter EngageでFlutter2が発表されトップページに概要が載っていたので、とりあえずどんなものか見てみました。
* ばっとナナメ読み＆youtubeの自動翻訳を参考にしているので、理解が違っている可能性がありますので、正確な情報はオリジナルサイト/動画の方で確認してください。

# サイト/動画
* https://events.flutter.dev/
* https://www.youtube.com/watch?v=IdrCyS7EF8M&t=10s

# 個人的な所感のまとめ
* Flutter2には超期待
* webがstableになった
* SurfaceDUO/iRobot/日立の例のようにWebや組み込みを含めた利用幅がすごく広がっている
* FirebaseやAdmobとの連携が強化されて使いやすくなりそう
* flutter fixというFlutter1からの移行ツールも便利そう
* Linux/Ubuntuでも開発できて、ますますどこでも開発できる!!

# Top 10 things you need to know about Flutter Engage
## 1. Flutter2=FreeUpgrade
* Flutterはモバイルフレームワークから、多種多様なプラットフォームで動くアプリになります
* windows,Mac,Linux,Webの4つで動作する
* モバイルアプリの95%を再利用してWeb版をつくれる

## 2. Google Pay Rewrote in Flutter for Productivity Gains
* GooglePayをFlutterで書き直した
    * 1.7MLから1.1Mに減少し、iOSエンジニアとAndroidエンジニアが効率的に開発を行えた

## 3. Microsoft contributing foldables support to Flutter
* MicrosoftのSurfaceDuoのような折りたためるスマートフォンにFlutterは対応した

## 4. Flutter Web Support
* Webプラットフォームサポートはstableになった
* スマホアプリでもWebのURLアクセスでもリーチできる

## 5. iRobot building multiplatform with Flutter
* irobotはルンバを作っている会社だが、コーディングロボットでもある
* ブラウザ上でflutterを使ったタブレットアプリと同じコードを作れる

## 6. Flutter is Canonical's default choice
* 各プラットフォーム毎にスタンドアロンで実行可能なファイルを作成できる
* linuxにもflutter sdkを公開しており、構築が簡単になった

## 7. Toyota infortainment systems powered by Flutter
* flutterは組み込みにも使える
* トヨタ自動車はFlutterを搭載したシステムを構築して、次世代の自動車に組み込んでいる

## 8. Sound null safety in Dart
* dartにnull safetyが導入され、null参照のバグの除去に役立つ
* null許容でない型を型システムに追加した
* flutter2の一部にflutter fixと呼ばれるツールがある
    * 昔に作ったflutterアプリがあり、非推奨メソッドがあったときに、QuickFixだけでなく、新しいAPIに自動的に移行できる
* VSCode,AndroidStudioでFlutterDevToolsは使える

## 9. Upgraded Firebase plugins for Flutter
* 現在Flutter/Dartのパッケージは15000以上ある
* Firebaseへの機能を「Authentication,Firestore,Functions,Messaging,Storage」などをアップグレードした

## 10. Google Mobile Ads SDK for Flutter
* Google Mobile Ads SDKで、既存のインラインバナーのオーバレイ以外も使える新しいプラグインを提供する
* pub.deskからgoogle_mobile_adsをダウンロードできる
Metamaskのweb3をVuexで管理する

# はじめに

metamaskを接続するのにちょっとつまづいたので共有
metamaskがinjectしたwindow.ethereumからweb3インスタンスを作成し，
Vuexのstoreで管理した．

# APIの規定
EIP-1193ではクライアントのAPIを規定している

https://eips.ethereum.org/EIPS/eip-1193

# 実装
## Store

今回ややこしいことはしてなく，接続できるかのテストで書いていたので
もしmetamaskがインストールされていなかったらなどの条件分岐は省いています

```store.js
import Web3 from 'web3'

export const web3Store = {
    namespaced: true,
    state: {
        web3: {}
    },
    getters: {
        getWeb3: (state) => {
            return state.web3
        }
    },
    mutations: {
        async mutateWeb3Provider(state) {
            if (window.ethereum) {
                await window.ethereum.request({ method: 'eth_requestAccounts' });
                const web3 = new Web3(window.ethereum);
                state.web3 = web3;
                return true;
            }
            console.log("fatal")
            return false;
        }
    },
    actions: {
        async setWeb3Provider({ commit }) {
            await commit('mutateWeb3Provider')
        }
    }
}

```

## 署名のテスト

```js
let prefix = "\x19Ethereum Signed Message:\n" + this.signMessage.length
let msgHash = this.web3js.utils.sha3(prefix+this.signMessage)
const signature = await this.web3js.eth.sign(msgHash, account)
```

# つまづいたところ

metamaskのドキュメント

https://docs.metamask.io
## Metamask上でログイン後，リロードしないとweb3がstoreに入らない

脳死で書いていたので`window.addEventListener`を書いていた．
どうやらこれが原因っぽい

```js

// 当初書いていたコード
mutations: {
        async mutateWeb3Provider(state) {
            window.addEventListener("load", async () => {
                if (window.ethereum) {
                    window.web3 = new Web3(window.ethereum);
                    state.web3 = window.web3;
                    console.log(state.web3);
                    window.ethereum.enable();
                    return true;
                }
                return false;
            });
        }
    },
```

## window.web3の非推奨

metamaskはwindow.ethereumを推奨しているらしい
でもmetamask以外をクライアントで使用した時のこと考えるとwindow.web3を対処する必要はある


## ethereum.enable()の非推奨

公式によると
> ## ethereum.enable() (DEPRECATED)
> WARNING
> Use ethereum.request({ method: 'eth_requestAccounts' }) instead.

を代わりに使おうとのこと`ethereum.request({ method: 'eth_requestAccounts' })`
Next.js + TypeScript + ESLint + Prettier 設定例

[JavaScript Standard Style](https://standardjs.com) を用いた設定

# Next.js プロジェクト作成
```
npx create-next-app project_name
cd project_name
```

# src ディレクトリにまとめる
```
mkdir src && mv pages styles src
```

# typescript の導入
```
mv src/pages/index.js src/pages/index.tsx
mv src/pages/_app.js src/pages/_app.tsx
mv src/pages/api/hello.js src/pages/api/hello.ts
yarn add --dev typescript @types/react @types/node
yarn build
```
ビルドすると `tsconfig.json` が生成される

# tsconfig の strict を true にする (Mac 版)
```:BSDのsed
sed -i '' 's/\"strict\"\: false/\"strict\"\: true/' tsconfig.json
```


# ESLint と Prettier の導入
```
yarn add --dev \
  eslint \
  prettier \
  @typescript-eslint/eslint-plugin \
  @typescript-eslint/parser \
  eslint-config-standard \
  eslint-config-prettier \
  eslint-plugin-standard \
  eslint-plugin-prettier \
  eslint-plugin-react \
  eslint-plugin-node \
  eslint-plugin-import \
  eslint-plugin-promise
```

# .eslintrc.json の設定
```
cat << EOF > .eslintrc.json
{
  "extends": [
    "standard",
    "plugin:prettier/recommended",
    "plugin:react/recommended"
  ],
  "plugins": ["@typescript-eslint"],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "rules": {
    "@typescript-eslint/adjacent-overload-signatures": "error",
    "prettier/prettier": [
      "warn",
      {
        "singleQuote": true,
        "semi": false
      }
    ],
    "yoda": "off",
    "react/prop-types": "off",
    "react/react-in-jsx-scope": "off",
    "import/first": "off",
    "no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars": [
      "warn",
      {
        "argsIgnorePattern": "^_"
      }
    ],
    "no-dupe-class-members": "off",
    "no-use-before-define": "off",
    "@typescript-eslint/no-use-before-define": ["error"]
  },
  "globals": {
    "fetch": false
  }
}
EOF
```

# おまけ（コミット）
```
git add .
git commit -m "init"
```
初学者がDockerを使ってDjango+gunicorn+nginx+PostgreSQLの環境を構築する

# Dockerfileを作成
```dockerfile:Dockerfile
FROM python:3.7

RUN apt-get update && apt-get install -y \
    nano
WORKDIR  /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt

RUN mkdir -p /var/run/gunicorn
#CMD ["gunicorn", "conf.wsgi", "--bind=unix:/var/run/gunicorn/gunicorn.sock"]
```

# requirements.txtを作成
```requirements.txt
Django
psycopg2
gunicorn
```

# docker-compose.ymlを作成
※一部修正しました・・・。

```yaml:docker-compose.yml
version: '3'

volumes:
  gunicorn:
    driver: local
  dbdata:

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: django
    ports:
      - '8000:8000'
    volumes:
      - './web:/code'
      #- './web/static:/static' # 不要だったかもしれません。。。
      - gunicorn:/var/run/gunicorn
    tty: true
    stdin_open: true

  nginx:
    image: nginx
    container_name: nginx
    ports:
      - '80:80'
    volumes:
      - './nginx/conf:/etc/nginx/conf.d'
      - './web/static:/static'
      - gunicorn:/var/run/gunicorn
    depends_on:
      - web

  db:
    image: postgres
    container_name: db
    ports:
      - "2345:5432"
    volumes:
      - "dbdata:/var/lib/postgresql/data"
    environment:
        - 'POSTGRES_DB=postgres'
        - 'POSTGRES_USER=postgres'
        - 'POSTGRES_PASSWORD=***'
        - 'POSTGRES_HOST_AUTH_METHOD=trust'
```

# ディレクトリを作る
```text:構成
.
├── Dockerifle
├── requirements.txt
├── docker-compose.yml
├── nginx
│   └── conf.d    # gunicornの設定ファイルを格納するため
└── web           # djangoプロジェクトを格納するため
```

# gunicornの設定ファイルを作成
```text:構成
.
├── docker-compose.yml
├── Dockerifle
├── requirements.txt
├── nginx
│   └── conf
│       └── gunicorn.conf    # コレを作成
└── web       
```

gunicorn.confの中身はこのような感じです。

```text:gunicorn.conf
upstream gunicorn-django {
    server unix:///var/run/gunicorn/gunicorn.sock;
}

server {
    listen 80;
    server_name localhost;

    location /static {
        alias /static/;
    }

    location / {
        try_files $uri @gunicorn;
    }

    location @gunicorn {
        proxy_pass http://gunicorn-django;
    }
}
```
# docker-composeでイメージをビルドし、コンテナを起動する
```
$ docker-compose up -d
```
$ docker-compose ps でコンテナが全てUpになっていることを確認します。

# djangoプロジェクトを作成
まずはdjangoコンテナに入ります。

```
$ docker-compose exec web bash
```

djangoプロジェクトを作成します。

```
$ django-admin startproject conf .
```

# settings.pyを変更
先ほど作成したdjangoプロジェクト内にあるsettings.pyのALLOWED_HOSTSを変更します。とりあえずどんなサーバーアドレスからのアクセスも受理することにしますが、必要に応じて変更した方が良いような気がします。。。

```python:settings.py
ALLOWED_HOSTS = ['*']
```
exitでコンテナから抜けます。 そして、一旦、コンテナをダウンさせます。stopでも良いかもしれません。

```
$ docker-compose down
```
次にDockerfileに追記します。

```dockerfile:Dockerfile
# 末尾に追加
CMD ["gunicorn", "conf.wsgi", "--bind=unix:/var/run/gunicorn/gunicorn.sock"]
```

再びDockerをupさせます。

```
$ docker-compose up --build -d
```

$ docker-compose psでコンテナがUpになっていることを確認したら、ブラウザからlocalhost:80にアクセスし、ロケットが飛び立っていることを確認します。
![スクリーンショット 2021-02-23 11.43.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689015/30a8ea2a-b620-1f4d-5da5-113608bf2b4e.png)
Windows XP のWindows インストーラー 4.5 を入れる

## きっかけ

* `Mono4`はインストーラーが古いと出るので、`Windows インストーラー`を更新する必要に気が付いた。調べてみると、`Windows Installer 4.5`というのがよさそうだ。

(`Mono2`と`Mono3`はXPに普通にインストールできる。)


## Windows インストーラー4.5のインストール

* [Download Windows Installer 4.5 Redistributable - 日本語 from Official Microsoft Download Center](https://www.microsoft.com/ja-jp/download/details.aspx?id=8483)は、まさかのリンク切れだったため

以下OSDNに上がっているのを発見した。
[Windows Installer_WindowsXP-KB942288-v3-x86.exe](https://osdn.net/projects/sfnet_vietnam-ldi/downloads/Software/Windows%20Installer%204.5/Windows%20Installer_WindowsXP-KB942288-v3-x86.exe/)

インストールしOS再起動。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/c812e8ed-970e-d0f7-d019-98e732125def.png)

結局、Mono 4 はインストールできなかった。

## Mono について

* https://download.mono-project.com/archive/

| Monoのバージョン | 備考 |
|:--:|:--|
| 2系 | XP にインストール可能 |
| 3系 | XP にインストール可能 |
| 4系 | Vista以降 |
| 5系 | 7以降 |
| 6系(最新) | 7以降 |


### Mono 3

XPで動かない

![mono3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/76b8351e-c683-45a3-f064-c43844116e9c.png)


### GTK# for .NET

まず`.Net 4.0`をインストールする必要がある様子。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/41fea0a0-1c88-eeb6-3f4e-6348a6b5253f.png)

* [Download Microsoft .NET Framework 4 (スタンドアロンのインストーラー) from Official Microsoft Download Center](https://www.microsoft.com/ja-jp/download/details.aspx?id=17718)
* [Download Update 4.0.3 for Microsoft .NET Framework 4 – Runtime Update (KB2600211) from Official Microsoft Download Center](https://www.microsoft.com/en-us/download/details.aspx?id=29053)
Docker buildできない際の原因【echoコマンド】

##前提
ホストOS：Windows（touchコマンドが使えない）

##起こったこと
下記イメージを作ろうとしたところ…

```Dockerfile:Dockerfile
FROM ubuntu:latest
RUN touch hoge
```

```
$docker build .
```
エラーがでました。

```
failed to solve with frontend dockerfile.v0: failed to create LLB definition: dockerfile parse error line 1: unknown instruction: 
��F R O M
```

##原因
Dockerfileのファイルを作成する際に、
WindowsOSのためtouchコマンドが使えず、
新規ファイル作成の際、echoコマンドを使っていましたが、
その使い方がNGでした。

具体的には下記がNG　

```
echo "" > Dockerfile
```
理屈は
①Dockerfileに空の文字列を挿入する。
②Dockerfileがないので空の新規ファイルが作られる。

なんですが、echoコマンドで出力すると、デフォルトで出力文字の最後が改行されるようで
それが原因なのか微妙（入力して修正するので）ですが、
-nオプションをつけると解決しました。

```
echo -n > Dockerfile
```
```
docker build .
```


原因曖昧であれなのですが、、
とにかく、echo "" > Dockerfileという書き方は使わないようにします。

参考：[echoコマンドの詳細まとめました【Linuxコマンド集】](hhttps://eng-entrance.com/linux-command-echo#-n)
手っ取り早くiPhoneでラズパイにsshしてみた

やっぱり外出先からも、自宅に立てたサーバーにsshしたいですよね。
そんな時、iPhoneが手元にあって、サーバーのsshがポート開放されていれば、なんとiPhoneから簡単なコマンドをssh経由で実行することができます。
ポート開放に関しては説明を省略しますので各自お調べください。

# iPhoneのショートカット
まずはこれを探す。
![D227FFB5-5BD8-48CA-BE0A-E1505DC6BEE3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/906971a3-fdd5-0cd9-5980-3390cd27ab9a.jpeg)
あったら開いて、画面の右上の「＋」をタップして新規作成する。
![9F029DD4-5E54-4E21-991C-A60522FA8871.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/1dd5b91e-e114-f949-aa29-46db6966ef51.jpeg)
アクションを追加
![6301C6AF-2B66-41D8-AA1E-C23DCE9F3CF8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/3f54afec-7118-5a35-cd67-0037451895d4.png)
追加するコマンドのところで、「ssh」と検索すると「SSH経由でスクリプトを実行」が出てくるので、それを選択する。
![8F9CD5EB-B3EC-4694-8FBB-198454FD045C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/6b5bf5f5-8586-34fd-6884-2278829a1da5.png)

表示を増やしてから必要な設定をしよう。
![03D950F7-98E9-4F75-9D20-0BEF2E8595A2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/dc3bce1c-e23e-8609-41ad-c1fca043bbac.png)

今回は、以下の記事で作成した「receiveMoisture.py」を実行したいので、そのようにスクリプトを記載する（ファイルは雑にデスクトップに置いたフォルダにまとめている）。
[植物の水やりをIoTする その３：Raspberry piを用いての給水タイミング制御](https://qiita.com/mashino-satoshi/items/8403bdbdc214e1682534)
![DE1E1219-4887-4E49-9BE3-E43DE8108A22.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/14ef3c07-163a-6ae1-555c-2661b56de9ae.jpeg)

このスクリプトを実行すると実行結果をコンソール上に表示するのだが、今回はこの受け取った値をアラートとして表示したい。
![E5AC7108-52EF-444E-B6B6-B9B5B53570BF.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/2750bac9-1045-4b74-4709-9cc123f047aa.jpeg)

スクリプティの
![CC0006C7-8012-4167-B847-BC237B3B7A9C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/bedd1f59-e015-665a-b6d1-5b377f25ceaa.jpeg)
通知→アラートを追加
とする。
で、「シェルスクリプトの結果を表示」にすると、本来コンソールに表示するはずだった値をピコンと表示してくれるようになる。
![0546A50E-13FC-4541-A385-3FE1CE132148.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/ec631000-33d6-9e28-3cdb-1efe26e5aff1.jpeg)

完成したら「・・・」の箇所を選択して、「ホーム画面に追加」をしておこう。
![2B8852FC-8EA6-413D-A3F5-C322584E0133.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/78166c4b-e283-96fb-691a-7a89628122ed.png)

できた！
![9E16DC72-04A4-4B85-8228-33BFEB8092C8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/c911c19f-2781-27a6-b6e7-08c1f8706946.png)
タップすると起動する。
![58272A17-3F3B-4598-9C5F-9199B98A0E01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/bec4dc9b-458e-b892-4e4b-d47834e927d0.png)
完了すると、値が表示される。
![4E4D1EAA-0BBF-4433-9C73-364B7943BA59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235422/c5737d75-3672-4a97-f1ed-87c1131cc3bb.png)
できた！

この値は、私が構築したアナログセンサーから取得した値をRaspberry piを経由して取得したものである。
自宅の観葉植物の乾燥具合をインターネットを経由しiPhoneで監視するという、プチIoTをこれで実現することができた。

ショートカットは便利なので今後も使っていきたいなあ。
python で関数合成的な何か

# 関数合成的な何か

```bash
$ python -V
Python 3.8.6
```

```a.py
import functools

class F:
    @staticmethod
    def __cmp(f1, f2):
        def __i1(*args1, **kwargs1):
            def __i2(*args2, **kwargs2):
                return f1(*args2, **kwargs2)
            return f2(__i2(*args1, **kwargs1))
        return __i1


    @classmethod
    def composite(cls, *fs):
        return functools.reduce(cls.__cmp, fs)

```

## test

```python:a_test.py
import pytest
import functools

from a import F

def test_args1():
    """1引数の関数合成"""
    def d1(a):
        r = a * 2
        print(f"d1: {a} * 2 = {r}")
        return r

    def d2(a):
        r = a + 1
        print(f"d2: {a} + 1 = {r}")
        return r

    def d3(a):
        r = a // 3
        print(f"d3: {a} / 3 = {r}")
        return r

    f = F.composite(d1, d2, d3, d1, d2)
    assert f(123) == 165

def test_args2():
    """2引数以上はできないので適当にカリー化するとよい"""
    def d1(a, b):
        r = a * b
        print(f"d1: {a} * {b} = {r}")
        return r

    def d2(a, b):
        r = a + b
        print(f"d2: {a} + {b} = {r}")
        return r

    d3 = functools.partial(d1, b=2)
    d4 = functools.partial(d2, b=1)
    d5 = functools.partial(d1, b=3)
    d6 = functools.partial(d2, b=4)

    f = F.composite(d3, d4, d5, d6)
    assert f(123) == 745


def test_args3():
    """2引数以上は(ry"""
    def d1(a, b, c):
        r = a // b - c
        print(f"d1: {a} // {b} - {c} = {r}")
        return r

    def d2(a, b, c):
        r = (a + b) ** c
        print(f"d2: ({a} + {b}) ** {c} = {r}")
        return r

    d3 = functools.partial(d1, b=5, c=5)
    d4 = functools.partial(d2, b=3, c=2)
    d5 = functools.partial(d1, b=345, c=3)
    d6 = functools.partial(d2, b=4, c=8)

    f = F.composite(d3, d4, d5, d6)
    assert f(123) == 256


```


## run test

```bash:bash
$ pytest -V
pytest 6.1.2

$ pytest -s -v a_test.py
=============================================== test session starts ===============================================
platform darwin -- Python 3.8.6, pytest-6.1.2, py-1.9.0, pluggy-0.13.1 -- /Users/kuryu/.pyenv/versions/3.8.6/bin/python3.8
cachedir: .pytest_cache
rootdir: /Users/kuryu/workspace/work
plugins: Faker-4.16.0
collected 3 items

a_test.py::test_args1 d1: 123 * 2 = 246
d2: 246 + 1 = 247
d3: 247 / 3 = 82
d1: 82 * 2 = 164
d2: 164 + 1 = 165
PASSED
a_test.py::test_args2 d1: 123 * 2 = 246
d2: 246 + 1 = 247
d1: 247 * 3 = 741
d2: 741 + 4 = 745
PASSED
a_test.py::test_args3 d1: 123 // 5 - 5 = 19
d2: (19 + 3) ** 2 = 484
d1: 484 // 345 - 3 = -2
d2: (-2 + 4) ** 8 = 256
PASSED

================================================ 3 passed in 0.06s ================================================
```

カレー食べたい。
TextFieldを隠さずにキーボードを表示させる方法-IQKeyboardManager

Keyboardが表示されて`TextField`が隠れてしまう時があると思います。
かと言って毎回Keyboardの高さ分画面を上にずらすと、元から画面上部にある`TextField`が画面外に行ってしまいます。
`TextField`の位置によって画面をずらすか判断する、ってこともできるかもしれませんが、毎回実装するのは面倒ですよね…。

実はその問題、先人が既に解決してくれています✨
その方法がこちらのGithubで公開されています→[IQKeyboardManager](https://github.com/hackiftekhar/IQKeyboardManager)
とても簡単ですが、英語で書いてあるので実装方法をまとめてみました。

#実装方法

まずはターミナルで実装したいプロジェクトが入っているフォルダに移動します。

次のコマンドで同じフォルダ内にCocoaPodsファイルを作成します。

```terminal
pod init
```

作成された`Podfile`を開き、次の記述を追加します。

```tex
# Pods for xxx(プロジェクト名)
pod 'IQKeyboardManagerSwift' ←追加
```

追加できたら`Podfile`を一旦閉じ、ターミナルで次のコマンドを打って`Podfile`をInstallします。

```terminal
pod install
```

すると`.xcworkspace`(アイコンが白いプロジェクト)が作成されるので、これを開きます。

`AppleDelegate.swift`ファイルを開き、次の箇所を追加します。

```swift
import UIKit
import IQKeyboardManagerSwift //←追加

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow? //←追加

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        IQKeyboardManager.shared.enable = true  //←追加

        return true
    }
```

これで完了です！
あとは開いて動作を確認してみてください。

![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843253/79dd5ba4-fee3-ff32-3ea0-41f6b9cf7523.gif)

#まとめ
いかがでしたでしょうか。とっても簡単ですね。

これは非常に便利なので、使わない理由がありません！

是非是非ご活用ください〜(それにしても先人は偉大ですね…)
よく使うSQLコマンド集

##データを更新
```UPDATE tbl_nm SET field_nm1=xxx, field_nm2=yyy WHERE field_nm3=zzz;```
##データを追加(全て）
```INSERT INTO tbl_nm (val1, val2, ...);```
##データを追加(指定の項目）
```INSERT INTO tbl_nm (field1,field2, ...) VALUES (val1, val2, ...);```
##テーブル定義変更
```ALTER TABLE tbl_nm ALTER COLUMN field_nm TYPE データ型;```
##シーケンス
###シーケンスを作成
```CREATE sequence シーケンス名```
###シーケンスの値を設定、初期化
```SELECT setval('シーケンス名', val);```
###任意のテーブルのシーケンス最大値+1にシーケンスを設定
```SELECT setval('シーケンス名', (SELECT MAX(id)+1 FROM tbl_name));```
###シーケンスの値を確認
```SELECT last_value FROM seaquence;```
###シーケンス削除
```DROP sequence シーケンス名```
D言語プログラムの--DRTオプション

D言語製のプログラムは、メイン関数の呼び出しの事前に、ランタイムでの処理でいくつかの特殊なコマンドライン引数を解釈し、ランタイムの制御を切り替える機能が備わっている。
細かな挙動は調べればわかるが、一覧になっている場所がないので、ここにまとめる。
以下に挙げるもの以外にも隠しオプションが存在しているようだが、ドキュメント化されていないなものは除外した。

# --DRT-testmode
単体テストの挙動を変更する。
https://dlang.org/phobos/core_runtime.html#.runModuleUnitTests

```d:例)テスト成功後にメイン関数を実行
myprog --DRT-testmode=run-main
```

### --DRT-testmode=test-or-main
デフォルトの挙動。
単体テストが存在する場合は単体テストを実行して、要約を表示して終了する。(メイン関数は実行されない)
単体テストが存在しない場合は、メイン関数を実行する。

### --DRT-testmode=run-main
単体テストがすべて成功した場合、メイン関数を実行する。

### --DRT-testmode=test-only
単体テストがすべて成功した場合であっても、メイン関数は実行しない。


# --DRT-covopt
カバレッジの挙動を変更する。
https://dlang.org/articles/code_coverage.html

```d:例)カバレッジの出力先を`cov`に指定して、既存の結果にマージする
myprog --DRT-covopt=merge:1 --DRT-covopt=dstpath:cov
```

### --DRT-covopt=merge:_\<cond\>_
- _\<cond\>_=`1`: 現在のカバレッジ結果を既存のレポートにマージ
- _\<cond\>_=`0`: 既存のレポートを上書きする。

### --DRT-covopt=srcpath:_\<path/to/dir\>_
_\<path/to/dir\>_ にはソースファイルを配置するパスを設定する。

### --DRT-covopt=dstpath:_\<path/to/dir\>_
_\<path/to/dir\>_ にはカバレッジ結果のレポートを書き込む場所のディレクトリのパスを設定する(この指定先のディレクトリは事前に必ず存在していなければならない)。


# --DRT-gcopt
ガベージコレクタの挙動を変更する。
https://dlang.org/spec/garbage.html#gc_config

```sh
app "--DRT-gcopt=profile:1 minPoolSize:16" arguments to app
```

### --DRT-gcopt=disable:_\<cond\>_
プログラム開始時にGCの有効無効を選択して起動する。

- _\<cond\>_=`0`: デフォルトです。プログラム開始時にGCが**有効**な状態で起動する。`core.memory.GC.disable()`で無効化する。
- _\<mode\>_=`1`: プログラム開始時にGCが**無効**な状態で起動する。`core.memory.GC.enable()`で有効化する。

### --DRT-gcopt=profile:_\<cond\>_
プログラム終了時にGCの使用状況分析結果を表示するオプション。

- _\<cond\>_=`0`: デフォルト。結果を表示しない。
- _\<cond\>_=`1`: 結果を表示します。

### --DRT-gcopt=gc:_\<mode\>_
GCの実装を選択できます。

- _\<mode\>_=`conservative`: デフォルト。保守的なGC。
- _\<mode\>_=`precise`: 正確なGC。
- _\<mode\>_=`manual`: マニュアル実行。`core.memory.GC.collect()`でGC実行。

### --DRT-gcopt=initReserve:_\<N\>_
_\<N\>_ MBのメモリを予約した状態でプログラムを起動する。

### --DRT-gcopt=minPoolSize:_\<N\>_
_\<N\>_ MBのメモリプールサイズを初期化した状態でプログラムを起動する。

### --DRT-gcopt=maxPoolSize:_\<N\>_
メモリプールサイズの最大を _\<N\>_ MBで指定する。

### --DRT-gcopt=incPoolSize:_\<N\>_
メモリプールサイズの増加ステップを _\<N\>_ MBで指定する。

### --DRT-gcopt=parallel:_\<N\>_
_\<N\>_個の追加スレッドを使用してマーキングを行います。

### --DRT-gcopt=heapSizeFactor:_\<N\>_
_\<N\>_で目標とするヒープサイズと使用メモリの比率を指定する。

### --DRT-gcopt=cleanup:_\<mode\>_
プログラム終了時に回収されていないのオブジェクトの扱い方を指定する。

- _\<mode\>_=`none`: 何もしない。
- _\<mode\>_=`collect`: デフォルト。回収する。
- _\<mode\>_=`finalize`: デストラクタを呼んでファイナライズする。


# --DRT-oncycle
スタティックコンストラクタが循環してしまった場合の挙動を指定できる。
https://dlang.org/spec/module.html#order_of_static_ctor

### --DRT-oncycle=abort
デフォルト。プログラムは強制終了する。

### --DRT-oncycle=deprecate
abortと同じように動作するが、循環が検出されると、ランタイムは欠陥のある2.072以前のアルゴリズムを使用して、循環が以前に検出されたかどうかを判断する。古いアルゴリズムで循環が検出されなかった場合、実行は継続されますが、非推奨のメッセージが表示される。

### --DRT-oncycle=print
検出されたすべての循環を表示し、実行は中止しない。循環が存在する場合、スタティックコンストラクタの順序は実装依存で、有効かどうかは保証されない。

### --DRT-oncycle=ignore
実行は中止しない。循環が存在する場合、スタティックコンストラクタの順序は実装依存で、有効かどうかは保証されない。
binding.pryを使用したエラー解決例


①controllerでbinding.pryを設定します。

```ruby
def create
    binding.pry
    comment = Comment.create(comment_params)
    redirect_to "/items/#{comment.item_id}"
  end
```

②ターミナルでcreateを確認すると、ROLLBACKが表示されています。

```ターミナル
[3] pry(#<CommentsController>)> comment = Comment.create(comment_params)
   (0.2ms)  BEGIN
  ↳ (pry):3:in `create'
  User Load (0.5ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 11 LIMIT 1
  ↳ (pry):3:in `create'
   (0.1ms)  ROLLBACK
  ↳ (pry):3:in `create'
=> #<Comment:0x00007fe2f9494f38 id: nil, user_id: 11, item_id: 24, text: "a", created_at: nil, updated_at: nil>

```

③comment.errors.full_messages　こちらの記述でエラーメッセージを取得します。

```ターミナル
[4] pry(#<CommentsController>)> comment.errors.full_messages
=> ["Tweet must exist"]
```

④バリデーションのエラーなのでmodels/comment.rbを確認します。

```ruby
class Comment < ApplicationRecord
  belongs_to :tweet
  belongs_to :user
end
```

⑤アソシエーションをitemに変更して修正完了です。

```ruby
class Comment < ApplicationRecord
  belongs_to :item
  belongs_to :user
end
```
【UE4】Control Rig試し中③／ぷちコン15進捗 - 2021/03/05

[1]:https://historia.co.jp/ue4petitcon15
[2]:https://pafuhana1213.hatenablog.com/entry/ControlRigComponent
[3]:https://www.unrealengine.com/marketplace/ja/product/control-rig-mannequin
[4]:https://www.unrealengine.com/marketplace/ja/product/graph-printer

[株式会社ヒストリアさん主催の第15回UE4ぷちコン][1]の作業進捗。
Control Rigの続き③。

# イマココ

とりあえずの動作確認で、Sequencer でシンプルなアニメーションを組んだ。
IK付きのリグだと、こういうのが作りやすくて助かる。
（IKというより、リバースフット(reverse foot)　←リバースフット最高！）

アキレス腱伸ばし。
![20210305_2014.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/9ca405f6-8cc0-293b-f1cc-ea42c2996b30.gif)

## Control Rig はこうなった

「[UE4.26で追加されたControl Rig Componentの使いかたについて <ControlRigの流用編> - ぼっちプログラマのメモ][2]」によると、ランタイムで動かすには ControlRigComponent が必要で、Control Rig Graph の方にも`Setup Event`の実装が必要とのこと。
…ということで、`Setup Event`, `Forward Solve`, `Backward Solve` の３つを組んだ。

とりあえず、記録としてスクショを貼るが、誰かの参考になる気がしない…
とにかくRig Graph の実装が地道すぎて地獄だった。
今後、途中でリグ階層に何かを足したり、何かを引いたりしたときに、`Setup Event`, `Forward Solve`, `Backward Solve`の対応がきっちりとれる気がしない。
ひたすら似て非なるコードを組み続けるので、ヒューマンエラーが入っている自信がある。

> 上述の[おかずさんのページ][2]に「つらい」と書いてあるが、まったくその通りでした…
> 本当に、Editor UtilityとかPythonとかで、自動作成した方がいい。

### リグ階層

見るからにしんどい感じ。
機能を盛り込みすぎた。
<img width="128px" alt="RigHierarchy" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/994d1b14-6cbd-a4f1-a971-4b0684dc6936.png">

### Setup Event

参考までに。（誰かデバッグしてください…）
どちらかというと、膨大さと地道さに愕然としてほしい気分です。
<img width="256px" alt="SetupEvent" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/e41c0431-56fd-2493-6a90-6415be2c33e4.png">
クリックすると拡大されます（だが、見る気にならない）

### Forward Solve

本体というべきところ。
<img width="256px" alt="ForwardSolve" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/44d5ec5d-6f50-2a20-e4b2-c9ed72a542c7.png">
クリックすると拡大されます（だが、見る気にならない）

### Backward Solve

こちらについては、まだ実際に動かしていないので、鵜呑みにはしないでください。
<img width="256px" alt="BackwardSolve" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/625e1635-9e82-54b7-9ec4-5a123c1c26c4.png">
クリックすると拡大されます（だが、見る気にならない）

# 気づいたこと：Replace Items のワナ

Epic Games提供の[Control Rig Mannequin][3]の中にこういうグラフがある。
<img width="400px" alt="ReplaceItems" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/ae3e3360-e2f2-feb2-2662-b906ed55bfc6.png">

- Children ノード
    - `hand_l`の子ボーンをまるっと取得（`index_01_l`, `index_02_l` とかの指ボーンたち）
- Replace Items ノード
    - Children ノードで取得できた子ボーンたちの名前の「_l」を「_r」に置き換えたボーンを取得
    - つまり、`index_01_r` とかの、右手の指ボーンたちが取得される。
- For Each Item ノード
    - これらのボーン群(＝両手の指ボーン全部)をループを回して処理

なるほど参考になるな！と真似して使っていたのだが、こういう(↓)名前のコントロール(…などのアイテム)があると、困ったことになる。

「Rig_LowerArm_L」

いかにも良く使いそうな名前だが、このコントロールの「_L」と「_R」を置き換えると、こういう(↓)名前になる。

「Rig<font color="red"><b>_R</b></font>owerArm<font color="red"><b>_R</b></font>」

こんな名前のコントロールはない！
右の Lower Arm (下腕) だけ処理が行われない事態が発生して、なぜ動かないのか気づくのに小一時間かかった。
皆さんもお気をつけて。

> なお、これらの文字列は Name 型なので、大文字小文字は区別されない。

# 追記：プラグインの紹介。Graph Printer最高です。

[Graph Printer][4]

ご存じの方も多いかも。
Blueprint グラフをまるっとスクショにしてくれます。
選択範囲のみをスクショにすることも可能。
無料です。
コンポネートの表示の仕方「reactメモ」


・コンポネートとは、reactの画面に表示される「部品」のことである。
・JSXのアタイの中でタグとして記述。
・<コンポネート名　/> の形。
⚠︎コンポネート名は大文字スタート

```react:react_app
<body>
    <h1>React</h1>
    <div id="root">wait.......</div>

    <script type="text/babel">
    let dom = document.querySelector('#root');
    
    const msg = {
     fontSize: "20px",
     fontWeight:"bold",
     padding: "10px",
     color:"white",
     backgroundColor:"darkblue",
     };

    //  ここから関数コンポーネート
    function Welcome(props){
      return <p style={msg}>Hello React!!</p>;
        }
    
    // 表示するコンポーネート
      let el = (
      <div>
        <Welcome/>
        </div>  
      );

      ReactDOM.render(el, dom);
    
    
    
    </script>
  </body>
```


・計算するコンポネート

```react:
let dom = document.querySelector('#root');
    
    const msg = {
     fontSize: "20px",
     padding: "10px",
     border:"double 5px magenta"
     };

     const msg2 ={
       fontSize: "16px",
       fontWeight: "bold",
       padding: "10px",
       backgroundColor:"cyan"
     };

    //  ここから関数コンポーネート
    function Calc(props){
      let total = 0;
      for(let i =1;i <= props.number;i++){
        total += i;
      }


    return <p style={msg}>1から, {props.number}までの
      合計は、「{total}」です。</p>;
  };
    // 表示するコンポーネート
      let el = (
      <div>
        <Calc number="100" />
        <Calc number="200" />
        <Calc number="300" />
        
        </div>  
      );

      ReactDOM.render(el, dom);
```
みんな 300US$分のAWS無料クレジット申請したよね？

はじめに：
この投稿は、AWSへ適当な内容で申請することを促してAWSを困らせようとかいう意図はありません(^0^;) あくまでもAWSの活用に少しでも興味ある人へのAWS有料機能の「お試し」利用を促進する意図でのご紹介ですw

# みんなお金ないよね？ね？

2020年の4月にフリーランスから再就職して以来、本業が多忙で全然個人的なプログラム開発をする体力と気力がなくて、AWSの無料枠期間ローテーションでDiscordのBGMボットのトラフィック課金をたまに支払っている程度なのですが、、、

2/28にAWSから随分昔にも一度見たことあるような美味しいキャンペーン？のメールが届きました。
AWS契約しているみなさんのところにも同様のメールが届いているはず。

正式には「AWS PoC ( Proof of Concept) プログラム」という名称みたいです。

![caf2a0a9944751768c7946687f3e2f4e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57876/e7b49545-699e-eb06-ccdf-b888be3a67a4.png)

## 『300 USD分のAWS無料クレジットを申請できます』

なんて素敵な響きでしょう。こんな素敵な日本語があったのか！(ハイスクールDxD風)

> お客様のビジネスに有効な PoC (概念実証) の構築も支援したいと考えています。

ここで、「趣味でAWS使ってるだけなので、PoCとか大層なことやらないし、個人だし・・・」
なんて思ってメールを読んだ瞬間に削除しちゃったあなた！ そうあなたですよ！

__モッタイナイ！！　そう、モッタイナイ なのです！__

メーラーからサルベージしてでも取り戻して申請しましょうww

## 趣味でAWS使っているだけの個人だけど大丈夫？

実際に届いたメールのリンクを踏むと以下のような申請画面に飛びます。

![5ddd9fd09d53f64661ba74f58340903f1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57876/70b3492f-8734-4896-342f-7d9bf39b44ac.png)

この申請項目で、「プロジェクトの目的」というメニューの選択肢は以下からの選択です。

・開発およびテスト
・スキルの学習と構築
・移行
・本番環境でのワークロード
・PoC (概念実証)

そう、PoC限定なんかじゃないんですよ。
「開発およびテスト」や「スキルの学習と構築」という__興味のある普段使いの内容で全然OK__なんです！

他の項目で悩ましいのは、あたかも企業でないと申請できないようないくつかの項目ですが、今流行りの？副業の一環も含めて__フリーランスを自称すればあなたは個人事業主！立派なお一人様組織__ですww

以下のように、ちゃんと選択肢を乗り越えられます。

・従業員数 → 社員は俺様1人で十分 (1～19人)
・想定予算 → 無料枠期間利用で課金ゼロでもOK (月額 50 USD未満)
・構築内容 → 以下から適当にどうぞ
　・AIと機械学習
　・バッチ処理
　・ビッグデータ、分析、ビジネスインテリジェンス
　・ビジネスアプリケーション – Microsoft
　・ビジネスアプリケーション – Oracle
　・ビジネスアプリケーション – その他
　・ビジネスアプリケーション – SAP
　・コンテンツ配信
　・ゲーム
　・IoT
　・トレーニングと認定
　・メディアサービス
　・移行
　・モバイルアプリケーション
　・その他
　・ストレージ＆バックアップ
　・ウェブサイトとウェブアプリ
　※途中に「その他」がある時点でAWS側もここはどうでもいい気がしますw
・御社名 → 屋号の登録していなくても、自分で「この屋号でやってます」と言えば自称フリーランスなら通るので適当に__迷惑がかからない実存しない名称__でもOK(笑)

## ポチっとな

フォームを埋めたら申請ボタンを「ポチっ」。

審査の結果は、私の場合1週間弱で審査通過でクレジット適用のメールが届きました＼(^O^)／

![8863e91dfbfde94be4a6bbe2a6c17b79.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57876/65d98db4-0a7f-b9ac-e2ab-89fda593c27b.png)

AWSコンソールのBilling画面でクレジットを確認すると、9/30期限まででちゃんと300 US$のクレジットが追加されています！

![c2850919a95d3afd1b25d7ff250aa1aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57876/a534a5bd-bdc1-0940-2714-316f0304ae70.png)

## 無課金勢が約3萬円分のクレジットを手に入れた！

__「約3万円分のAWSクレジットがある」というだけで、急にプログラム開発のモチベーションがあがりますww__
週末に疲れて引き籠もるのが常のフルリモート社畜でもなんか作ってみようと立ち上がるってものです(苦笑)

あとは、強化学習系のスポット課金にでも、SageMakerの従量課金でも、各種サービスの無料枠超過分にでも充当しましょう♪

なお、支給されたクレジットは、課金発生後に自動で充当されますので、ときどきBilling画面でクレジット残額を確認しながら使いましょう。調子に乗って、300 US$使い切って高額請求が来ても当局は一切責任を負いませんよ！
ページ離脱時や、遷移した時に出る画面の上下中央に出るバナーのCSS

# どうも7noteです。最近よく見かける離脱防止用のバナーの作り方

たとえばこんなやつですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/080f4640-7fd4-4b23-17eb-e84bab47e284.png)

https://www.try-gakuin.com/#cm

これと同じようなものを作ってみます。


**どんっ！！**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/f6f47e02-b36e-f549-cf35-3bf7a498e24f.png)

## 画面いっぱいを暗くして、バナーを表示する方法

```index.html
<!-- body直下に設置 -->
<div id="overview">
  <div class="bnr"><img src="sample.png" alt=""><span class="close">×</span></div>
</div>
```

```style.css
#overview {
  width: 100%;       /* 幅いっぱい */
  height: 100vh;     /* 高さいっぱい */
  background: rgba(0, 0, 0, 0.5); /* 背景を薄暗くする */
  display: none;     /* デフォルトは非表示 */
  position: fixed;   /* 表示位置を絶対指定して固定 */
  top: 0;            /* 表示位置を上から0pxに指定 */
  left: 0;           /* 表示位置を左から0pxに指定 */
}

#overview .bnr {
  position: absolute; /* 相対位置とする、かつcloseの基準値になる。 */
  top: 50%;           /* 表示位置を上から50%に指定 */
  left: 50%;          /* 表示位置を左から50%に指定 */
  transform: translate(-50%, -50%); /* 上下中央にするため要素の半分分だけ左上に戻す */
}
#overview .bnr .close {
  font-weight: bold;  /* 太字にする */
  padding: 0 6px;     /* 左右の余白を適当に調整 */
  background: #fff;   /* 背景色を白に指定 */
  position: absolute; /* 相対位置とする */
  top: -28px;         /* いい感じの位置に指定 */
  right: 0px;         /* 同様 */
  cursor: pointer;    /* hover時にカーソルを指の形にする */
}
```

```script.js
/* ページ読み込み完了時にバナーのブロックを表示 */
window.onload = function(){
  $("#overview").show();
}

/* ×ボタンが押されたとき、バナーブロックを非表示 */
$("#overview .close").on("click", function(){
  $("#overview").hide();
});
```

## 解説


CSSの解説ですが、ポイントがいくつか。overflowの幅は100vwにしてしまうとpcの縦スクロールバー分の計算をしないといけなくなってしまうので、body直下に設置し、`width: 100%;`を指定しています。

一番後ろのoverflowに半透明の背景を入れるため16進数での背景指定ではなく`background: rgba(0, 0, 0, 0.5);`と書き、色の透明度で調整。opacityで透明度を指定してしまうと、バナー画像も半透明になってしまうので注意。
詳しくは過去の記事「[【初心者でもわかる】cssで使われる透明3種類の使い方](https://qiita.com/7note/items/a5975366cef5e169506d)」をご覧ください。

あとはバナー画像を上下中央に設置したり、×ボタンをいい感じのところに配置したら完成！
×ボタンは押せることがわかるように`cursor: pointer;`を入れておくのがベスト！

## まとめ

見た目の体裁についての解説になります。記述しているjsはおまけ程度にお考えください、実運用できるようなレベルのjavascriptではありません。
このままだと、1回バナーを見たユーザーに何度も表示することになりますし、ページリロードする度にバナーが出てくる等、使いにくさが出てくきます。

離脱時（戻るボタンを押したとき）にバナーを出すなどは意外と手間がかかるのでjs初心者の方はあまりお勧めしないかも。。。そういうツールもあるので、ちゃんと運用したいのであればそのようなツールを導入することを検討するといかも

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
RailsのActiveModel::Modelを使用している場合のエラーメッセージの日本語化について

Railsのエラーメッセージを日本語化する方法に関しては様々な記事が上がっており、ある程度簡単に実装できると思います。
しかしそんな中で私のような初学者は細かいところで壁にぶつかったりするものです、、
今回は以下の記事を参考にしつつ、私がぶつかったActiveModel::Modelでのエラーメッセージの日本語化を、背景知識と合わせて記録しておきます。

# 開発環境
Mac OS Catalina 10.15.7
ruby 2.6.5
rails 6.0.0

# ActiveModel::Modelとは
ActiveModelというのはActiveRecordパターンに従わずに作成したモデルとのやり取りを可能にするためのライブラリです。
（出典：Railsガイド）
https://railsguides.jp/active_model_basics.html

とてもざっくりいうと、ActiveRecordパターンに仕方って作成したモデルというのは

```rb
class Post < ApplicationRecord
...
```

のように、```ApplicationRecord```クラスのサブクラスとして生成されたクラスのことです。
逆に、非ActiveRecordモデルとは

```rb
class Post
```
というものです。


```ActiveModel::Model```というのはAction Viewヘルパーメソッド（```form_for```や```render```）を使えるようにするモジュールです。

私の場合は記事投稿機能にタグ付機能を追加したく、PostTagというモデルを自作し、そこにActiveModel::Modelを導入しました
※具体的にどのような場面でタグ付機能を使うのかはこの記事で言いたいことから外れるので、下記他の方が書かれている記事をご参照いただければと思います
https://qiita.com/kazuma_M/items/d0c87522f9298e3c07c0


# エラーメッセージの日本語化
本記事は、「ActiveModel::Modelのバリデーションエラーメッセージを日本語化したい」というニッチな分野に対しての解決手法を扱うものですので、ここからが本番。

エラーメッセージの日本語化は、以下の通り行います

```ruby:conflg/application.rb
module "アプリケーション名"
class Application < Rails::Application
   config.load_defaults 6.0
   # 日本語設定
   config.i18n.default_locale = :ja
　　# 省略
 end
end
```

続いてgemfileの`rails-i18n`を導入します

```ruby:Gemfile
gem 'rails-i18n'
```

そしてターミナルで

```
bundle install
```

します。これだけでは不十分なので、`config/locale`ディレクトリに`ja.yml`ファイルを作成し、日本語化の設定を行います。
（以下例では仮にActiveRecordパターンに基づいて作成されたTweetモデルというものが存在すると仮定しています）

```ruby:config/locale/ja.yml
ja:
  activerecord:
    attributes:
      # Tweetモデルが存在すると仮定します
      Tweet:
        title: タイトル
        text: テキスト
```

ではこれに倣い、ActiveModel::Modelを使用しているモデル（ここではPostsTagとします）の日本語化登録をします

```ruby:config/locale/ja.yml
ja:
  activerecord:
    attributes:
      # Tweetモデルが存在すると仮定します
      tweet:
        title: タイトル
        text: テキスト
      posts_tag:
        theme: テーマ
        content: 内容
        tag_name: タグ
```

しかしこれでは変わりません。なぜなら`activerecord`内に登録をしているからです。

こうすることで正しく日本語化の登録ができます

```ruby:config/locale/ja.yml
ja:
  activerecord:
    attributes:
      tweet:
        title: タイトル
        text: テキスト
  # activemodelを作成します
  activemodel:
    attributes:
      posts_tag:
        theme: テーマ
        content: 内容
        tag_name: タグ
```




ということで、かなり簡単ですがja.ymlの読み方とモデルの種類を理解していないと意外と解決できない日本語化問題の解決法でした。

間違っている点やわかりにくい点があればご指摘ください！
[Laravel]リレーション先のデータもファクトリでまとめて作成

#概要
テストを実装している時に一対一、または一対多のテーブルの情報があり、リレーション先のデータごとまとめて`Factory`で作成したい時の方法をメモします。

例えば特定のUserと紐づいたPostを作成したいときなどに使えます。

ここではファクトリでのテストデータ作成方法には触れません。

#環境
Laravel v8.12

#実装
一対多テーブル
User→一
Post→多

##Userからアクセス

```Test.php
$user = User::factory()->has(Post::factory())->create();
```
Postの数を指定することもできます。

```Test.php
$user = User::factory()->has(Post::factory()->count(3))->create();
```

##Postからアクセス

```.php
$posts = Post::factory()->count(3)
    ->for(User::factory()->state([
        'name' => 'hogehoge',
    ]))
```


#参考文献
[公式](https://readouble.com/laravel/8.x/ja/database-testing.html)
aptlyを用いたDebianローカルリポジトリ構築

## 背景

Ubuntuの環境構築を行う際、パッケージの更新やインストールを行いますが、環境によってはインターネット接続が制限されるケースもあると思います。そのような場合、Debianパッケージのローカルリポジトリを構築して、そこからパッケージをインストールしたくなりますが、その際の手順を調べたので記事にまとめてみます。本記事では **aptly** というDebianリポジトリ管理ツールを扱います。

## 環境

* Ubuntu 18.04 (Amazon EC2 Instance)

## 実施手順

まずaptlyをインストールします。

```
# sudo apt-key adv --keyserver pool.sks-keyservers.net --recv-keys ED75B5A4483DA07C
# apt-get update
# apt-get install aptly
```

ローカルミラーを作成し、リモートミラーコンテンツと同期します。筆者の環境では2時間くらいかかりました。

```
# gpg --no-default-keyring --keyring trustedkeys.gpg --key-server keys.gnupg.net --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32

# aptly mirror create -architectures=amd64 ubuntu-mirror   http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty
# aptly mirror update ubuntu-mirror
```

```:出力
Downloading http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/dists/trusty/InRelease...
Downloading http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/dists/trusty/Release...
Downloading http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/dists/trusty/Release.gpg...
gpgv: Signature made Thu May  8 14:20:33 2014 UTC
gpgv:                using DSA key 40976EAF437D05B5
gpgv: Good signature from "Ubuntu Archive Automatic Signing Key <ftpmaster@ubuntu.com>"
gpgv: Signature made Thu May  8 14:20:33 2014 UTC
gpgv:                using RSA key 3B4FE6ACC0B21F32
gpgv: Good signature from "Ubuntu Archive Automatic Signing Key (2012) <ftpmaster@ubuntu.com>"
Downloading & parsing package files...
Downloading http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/dists/trusty/main/binary-amd64/Packages.bz2...
Downloading http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/dists/trusty/restricted/binary-amd64/Packages.bz2...

(...略...)
```

スナップショットを作成します。

```
# aptly snapshot create ubuntu-mirror-20210304 from mirror ubuntu-mirror
```

リポジトリコンテンツを格納するS3バケットを作成し、静的ウェブサイトホスティングを有効にします。作成したS3バケットに対してpublishします。

```
# export AWS_ACCESS_KEY_ID="xxxxxxxx" AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxx"
# aptly publish snapshot --skip-signing ubuntu-mirror-20210304 s3:your-repo-bucket:
```

`~/.aptly.conf` ファイルの `"S3PublishEndpoints"` を以下のように編集します。

```:~/.aptly.conf
{
  "rootDir": "/root/.aptly",
  (...略...)
  "S3PublishEndpoints": {
    "your-repo-bucket": {
      "region": "ap-northeast-1",
      "bucket": "your-repo-bucket",
      "acl": "public-read"
    }
  },
  "SwiftPublishEndpoints": {}
}
```

2回目以降のpublishには以下のコマンドを実行します。

```
# aptly publish --skip-signing switch trusty s3:your-repo-bucket: ubuntu-mirror-20210304
```


## 動作確認

構築したリポジトリからインストールするよう `/etc/apt/sources.list` を編集します。

```:/etc/apt/sources.list
deb http://your-repo-bucket.s3-website-ap-northeast-1.amazonaws.com/ trusty main
```

例として `apache2` をインストールしてみます。

```
# apt-get update --allow-insecure-repositories --allow-unauthenticated
# apt-get install apache2
```

筆者の環境では無事インストール出来ました。

## 参考

* [aptly](https://www.aptly.info/)
* [aptlyによるaptリポジトリ管理 | クックパッド開発者ブログ](https://techlife.cookpad.com/entry/2014/11/07/100000)
TD-Gammon でお試し結果

[TD-Gammon でお試し](https://qiita.com/mkisono/items/77c238c8121d79cb7622)の結果を書いておこう。

![スクリーンショット 2021-03-05 080012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42252/ca01dc7e-e8c0-b7a0-767b-a682984c44bd.png)

自己対戦を 1,000,000回繰り返した結果である。10万回学習するごとに、gnubgと100回対戦し、XGで解析した。ご覧の通りPRの改善傾向は続くものの、まだ初心者レベルである。
キューブアクションは学習していないので改善する余地が無いはずだが、グラフは若干右上がりである。おそらく、ムーブが改善するにつれ、キューブエラー場面のエラー値が小さくなっているのだろう。

棋譜を確認すると、botのプレイには大きく2つの問題があった。

## "ギャモン"を知らない

バックギャモンでは、普通に勝つと１点が得られるが、特定の条件を満たすとギャモン勝ち=2点、バックギャモン勝ち=3点が得られる。今回お試しした実装では、勝った時の reward は常に１点で、ギャモン勝ちをしようが見返りがないのである。よってギャモンを目指す手や、ギャモンセーブする手が見過ごされる傾向にあると思った。

5ゾロブリッツが覚醒していない図。
![スクリーンショット 2021-03-05 193441.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42252/d3c915f0-a486-2717-5e2d-efd0be9d8ee3.png)

ギャモンセーブなんて教わってませんの図。
![スクリーンショット 2021-03-05 194437.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42252/a6e627f0-40ef-de79-78a8-50469326ebbe.png)


## ベアオフが下手くそ

理由は定かではないが、ベアインやベアオフで大きなエラーが散見される。gnubg や XG は、ベアオフデータベースなるものが存在し、終盤ではニューラルネットに頼っていないようだ。

以下よりもっと単純なポジションでエラーしている例もある。
![スクリーンショット 2021-03-05 194824.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42252/f1505b02-510e-4996-2c96-a4a62acd2a7e.png)

## とにかく、まだまだですね

この子が弟子だったら、破門にしたいようなムーブが山盛りです。
![スクリーンショット 2021-03-05 193145.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42252/9344b615-1477-054b-28df-442d9651359c.png)
![スクリーンショット 2021-03-05 193337.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42252/bde24de1-6fdf-0c20-c6ae-9b9ebd45c1fe.png)

## これから

TD-Gammonでの学習はこれくらいにして、強化学習理論の勉強や Agent の実装、または使える既存の実装を吟味していこうと思います。