OmniAICreator/Qiita-1.07M huggingface dataset:
Windows XP SP3のIE6でも見れるwebサーバー設定(Let's Encrypt版)

* [Windows XP SP3のIE6でも見れるwebサーバー設定(自己署名証明書)
) - Qiita](https://qiita.com/tukiyo3/items/340d5e18b6db6404c02c)

## IE6で見れるwebサーバー設定

* cert.pem ← 不要
* chain.pem ← 不要
* fullchain.pem ← `必要`
* privkey.pem ← `必要`


```nginx:ssl.conf
server {
    listen       443 ssl;

    ssl_certificate      /opt/ssl/fullchain.pem;
    ssl_certificate_key  /opt/ssl/privkey.pem;

    ssl_session_timeout  5m;

    ssl_protocols  SSLv2 SSLv3 TLSv1;
    ssl_ciphers  DES-CBC3-SHA;
    ssl_prefer_server_ciphers   on;
}
```

```sh:run.sh
docker run \
 --name ssl443 \
 --rm \
 -d \
 -p 443:443 \
 -v $(pwd)/data/ssl.conf:/etc/nginx/conf.d/ssl.conf \
 -v $(pwd)/data/ssl/:/opt/ssl/ \
 -v $(pwd)/data/html/:/etc/nginx/html/ \
 nginx:1.11
```

* nginx 1.11 までがxp対応 (`DES-CBC3-SHA`が使える。)
Firebase個人メモ

https://firebase.google.com/docs/firestore/data-model?hl=ja

https://www.virment.com/save-data-to-firestore-vue-js-form/


https://qiita.com/sgr-ksmt/items/1a731fdadf06119d35fc

https://qiita.com/sgr-ksmt/items/1a731fdadf06119d35fc


https://tech-blog.sgr-ksmt.org/2018/12/11/194022/

https://crieit.net/posts/Nuxt-js-Firestore-SSR

https://firebase.nuxtjs.org/guide/usage/

https://upd.world/nuxtjs-deploy-firebase-hosting/

https://blog.engineer.adways.net/entry/2018/11/02/150000

https://firebase.google.com/docs/rules/basics?hl=ja

https://firebase.google.com/docs/firestore/security/rules-structure?hl=ja

https://firebase.google.com/docs/firestore/security/rules-conditions?hl=ja

https://firebase.google.com/docs/firestore/security/get-started?hl=ja

https://firebase.google.com/docs/firestore/security/rules-conditions?hl=ja

https://firebase.google.com/docs/firestore/query-data/queries?hl=ja
Ionic Vue のデフォルト言語をTypeScriptからJavaScriptに修正する

# 前提

- 2020年10月15日にionic vue が正式リリースされました。
- ionic vue のデフォルト言語TypeScriptでした。

# 目的
- ionic vue の開発言語をTypeScriptからJavaScriptに変更したいと思います。

# 修正

- TypeScriptのModuleを削除する

```sh
$ npm uninstall --save typescript @types/jest @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/cli-plugin-typescript
```

- `router/index.ts` と `main.ts` の拡張子を `.ts` から `.js` に変更する

- `.eslintrc.js` を下記のように修正する

```javascript:.eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true
  },
  'extends': [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    - '@vue/typescript/recommended' // 削除
  ],
  parserOptions: {
    ecmaVersion: 2020
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'vue/no-deprecated-slot-attribute': 'off',
    - '@typescript-eslint/no-explicit-any': 'off', // 削除
  },
  overrides: [
    {
      files: [
        '**/__tests__/*.{j,t}s?(x)',
        '**/tests/unit/**/*.spec.{j,t}s?(x)'
      ],
      env: {
        jest: true
      }
    }
  ]
}
```

- 先程ファイルの名前を変更した`router/index.js` から `Array<RouteRecordRaw>` を削除する

```javascript:index.js
import { createRouter, createWebHistory } from '@ionic/vue-router';
import { RouteRecordRaw } from 'vue-router';
import Page1 from '../views/page1.vue';
import Page2 from '../views/page2.vue';

const routes = [ //  ここを変更
  {
    path: '/',
    redirect: '/page1'
  },
  {
    path: '/page1',
    name: 'Page1',
    component: Page1
  },
  {
    path: '/page2',
    name: 'Page2',
    component: Page2
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router
```


# 感想
- TypeScriptからJavaScriptへの変更はそんなに煩わしくなく変更することができた。
urllib.requestのプロキシ設定



urllib3==1.25.10
python==3.7.9

#プロキシで通らなかった時

```python
import urllib.request

proxy_set = urllib.request.ProxyHandler({'http' : 'http://123.11.111.111:0000',
                                             'https': 'https://123.11.111.111:0000'})
opener = urllib.request.build_opener(proxy_set)
prox = urllib.request.build_opener()
urllib.request.install_opener(prox)
```


こうしておくとMNISTとかがkeras(tf.keras.datasets,keras.datasets)から引っこ抜ける。

#以上
Laravelの日本語化ファイルを編集し、バリデーションメッセージの:valueや:dateなどのプレースホルダーを日本語化する

Laravelを日本語化し、言語ファイルのvalidation.phpを編集することで、バリデーションメッセージを日本語化することができます。

attributesメソッドを編集することで英語の属性名も日本語化できるので、例えば年齢入力欄の属性名をageにしていても、

> ageには、数字を指定してください。

ではなく、

> 年齢には、数字を指定してください。

と表示することが可能です。

## 問題

ただ、attributesメソッドを追加しても、:dateなどのプレースホルダーは日本語化されないため、一部日本語化されない箇所があります。

例えば、以下のような例です。

まず、日本化していない場合は[Laravelの言語を日本語に変更](https://qiita.com/mitashun/items/160784ce352cf529f853)の記事に沿って日本語しておきます（インストーラのダウンロードでは対応したバージョンを指定します）。

次に、make:requestコマンドでフォームリクエストクラスを作成します。

```Shell:CLI
php artisan make:request ExampleRequest
```

バリデーションルールを追加します。

```php:app/Http/Request/ExampleRequest.php
public function rules()
{
    return [
        'deadline' => 'required|date|after_or_equal:today',
    ];
}
```

ここでは、deadline（締切日）という属性に、

- 必須
- 日付文字列
- 本日以降

というルールを設定しました。

次に、カスタムバリデーション属性名を設定するため、attributeメソッドを追加します。

```php:resources/lang/ja/validation.php
'attributes' => [
    'deadline' => '締切日',
],
```

これによって、例えばrequiredのバリデーションに失敗した場合の表示が

> deadlineは必ず指定してください。

から

> 締切日は必ず指定してください。

という表示に変わります。

### :valueや:dateなどのプレースホルダーを日本語に置き換えたい

しかしながら、after_or_equalのバリデーションメッセージは

```php:resources/lang/ja/validation.php
'after_or_equal'       => ':attributeには、:date以降の日付を指定してください。',
```

となっているため、:dateプレースホルダーの部分は、attributeメソッドでも置き換えられず、after_or_equalのバリデーションに失敗した場合、

> 締切日には、today以降の日付を指定してください。

という表示になってしまいます。

## 解決策

:valueや:dateなどのプレースホルダーを変更する場合は、valuesメソッドを使います。

:valueプレースホルダーの変更方法は、ドキュメントの[言語ファイルでカスタム値を指定](https://readouble.com/laravel/8.x/ja/validation.html#localization)に記載があります。

:dateプレースホルダーの変更は、次のように記述します。

```php:resources/lang/ja/validation.php
'values' => [
    'date' => [
        'today' => '本日',
    ],
],
```

これによって、

> 締切日には、本日以降の日付を指定してください。

と表示されるようになります。
Flutter(Dart)でListのforEachでasync, awaitを利用する時にはまったこと

## うまくいかなかった記述
#### ①自分なりに実装

```dart:例1（list.forEachでasyncとawaitつけた）
void main() async {
  List<int> list = [1, 2, 3, 4, 5];
  
  // 1秒ごとに実行して欲しい
  list.forEach((num) async {
    await Future.delayed(Duration(seconds: 1));
    print(DateTime.now());
    print(num);
  });
  
  // ↑上の処理が終わったら実行して欲しい
  print(DateTime.now());
  print('Finish');
}
```

```dart:結果1（Finishが先になってしまい、ループ処理も1秒ごとじゃない）
2020-10-19 11:33:01.140
Finish
2020-10-19 11:33:02.141
1
2020-10-19 11:33:02.141
2
2020-10-19 11:33:02.141
3
2020-10-19 11:33:02.141
4
2020-10-19 11:33:02.142
5
```

#### ②こちらの記事を参考に m(_ _)m
[List.forEachでasync, awaitしたいならFuture.forEachを使おう](https://patorash.hatenablog.com/entry/2017/12/15/024453)

```dart:例2（list.forEach→Future.forEachに変更）
void main() async {
  List<int> list = [1, 2, 3, 4, 5];
  
  // 1秒ごとに実行して欲しい
  Future.forEach(list, (num) async {
    await Future.delayed(Duration(seconds: 1));
    print(DateTime.now());
    print(num);
  });
  
  // ↑上の処理が終わったら実行して欲しい
  print(DateTime.now());
  print('Finish');
}
```
```dart:結果2（1秒ごとにはなっているがまだFinishが先に来てる）
2020-10-19 12:06:42.782
Finish
2020-10-19 12:06:43.785
1
2020-10-19 12:06:44.789
2
2020-10-19 12:06:45.793
3
2020-10-19 12:06:46.795
4
2020-10-19 12:06:47.797
5
```

## うまくいった記述
惜しかった...

```dart:例3（Future.forEachの前にawaitをつけた）
void main() async {
  List<int> list = [1, 2, 3, 4, 5];
  
  // 1秒ごとに実行して欲しい
  await Future.forEach(list, (num) async {
    await Future.delayed(Duration(seconds: 1));
    print(DateTime.now());
    print(num);
  });
  
  // ↑上の処理が終わったら実行して欲しい
  print(DateTime.now());
  print('Finish');
}
```
```dart:結果3
2020-10-19 12:09:46.037
1
2020-10-19 12:09:47.038
2
2020-10-19 12:09:48.040
3
2020-10-19 12:09:49.041
4
2020-10-19 12:09:50.042
5
2020-10-19 12:09:50.043
Finish
```
【PHP】public・protected・private 適当に決めてない？

突然ですが
メソッドの前につける **public・protected・private**
適当に決めている人いませんか？

はい、僕です。

**「これはまぁどこからも呼ばない気がするし private でいいかな。。」**
**「うーんこれあとで他で使いそうだなぁ。。。いや微妙だなぁ。。。よしとりあえず protected にしとくかっ。」**

はい、僕です。

ということで、今回は いわゆる **アクセス修飾子** について、
「可読性」という視点から、改めて考えたいと思います。

まず、おさらいです。

・**public**・・・どこからでもアクセス可能
・**private**・・・継承先のサブクラスからアクセス可能
・**protected**・・・そのクラスからのみアクセス可能

ですね。

それは知ってるんです。それはみんな知ってるんですよ！！
知ってるだけで使えないんだったら、なんの意味があるっていうんですか！！！
<img src="https://mk8-robo.com/wp-content/themes/mk8-robo/story/story-b/images/frame_8.png" width="300">
はぁはぁ。。。
何なんだこれは。。。

話は変わりますが、
『人生』には、どうやっても変えられないものと、変えることができるものがあります。
過去の偉人たちも言っています。

民よ。変えられない「過去」に嘆くのならば、変えられる「未来」を見ようではないか。 
by **ナポレオン**

「他人」は変えることはできない。変えることができるとしたら、それは「自分」である。
by **アドラー**

相手の「変」なところを変えようとしないで、心で受け入れようよ。そしたらそれが「恋」に変わるからさ。
by **紫式部**

すいません嘘です。ググっても出てきません。

そんな感じで、クラス設計をする際も、
変えることができる属性と、変えることができない属性を、
明確に定義しておいた方がいいですよね。

では**『人生』**ではなく「牛丼」で考えてみましょう。

◯屋の牛丼を頼み、カウンターに置かれました。
この時点で、変えることができるものと、変えることができないものって何でしょう？

**「牛丼を食す上で変えられないもの」**
・ごはんの量
・値段

**「牛丼を食す上で変えることができるもの」**
・紅生姜の量
・お箸で食べるか、スプーンで食べるか

```php:GyuDon.php
class GyuDon {
	private $riceAmount = 200; // ごはんの量
	private $price = 350; // 値段
	public $beniSyoga = '3袋'; // 紅生姜の量
	public $useChopsticks = true; // お箸を使う
}
```
変えることができないものというのは、
変えようとすると怒られます。

ごはんの量を変えてみましょう。

```php:main.php
$gyudon = new GyuDon();

$gyudon->riceAmount = 300; // エラーが起きる
```

みなさん想像してみてください、牛丼が出されたあとに、
やっぱりご飯を大盛りにしてくれと頼んだら、確実に嫌な顔をされますよね。

次に、紅生姜の量を増やしてみようと思います。

```php:main.php
$gyudon = new GyuDon();

$gyudon->beniSyoga = '10袋'; // エラーは起きない
```

はい、紅生姜をいくら盛ろうが、誰にも怒れませんね。
# 最後に
private・protected・public を なんとなくではなく、
変えることができるものと、変えることができないもの、という観点で決めるようにすると、
よりオブジェクト指向を深く理解できるのではないでしょうか。

それでは、みなさん、紅生姜は常識の範囲内でね:no_good:
【Bootstrap】グリッドシステムを入れ子で実現

今回は皆さん、ご存知 Bootstrap についてです。

世界で最も人気の CSS フレームワーク。
この芸能界の次に入れ替わりが激しいと言われる ITの世界 において、
CSS フレームワーク人気の王座に Bootstrap は、開発当初の 2011年 から座り続けられておられます。

そして人気の大きな理由の一つにグリッドシステムがあります。
そうです、画面サイズによってウニャウニャする、あれです。
（画面を横幅のサイズごとに、12分割にし、指定した数字分の範囲を確保する仕組みですね。）

今回は確保した範囲内でさらに 12分割 をする方法をご紹介します。
まず、画面を普段通りのやり方で 3分割 にします。
画面を 3分割 するには、全部で 12分割 するうち 4分割分 を確保すればOKですね。

```html:bootstrap.html
<body>
    <div class="container">
        <div class="row">
            <div class="col-4" style="background-color: blue; height:100vh">
            </div>
            <div class="col-4" style="background-color: white; height:100vh">
            </div>
            <div class="col-4" style="background-color: red; height:100vh">
            </div>
        </div>
    </div>
</body>
```

![スクリーンショット 2020-10-19 5.02.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661269/35b5c1df-cd3a-5b95-8679-13cf7bcc6a3d.png)

さぁ今回はさらに、この真ん中の白い部分を 3分割 します。
まず、3分割したいブロック要素の中に、row クラスのブロック要素を記述します。

```html:bootstrap.html
<body>
    <div class="container">
        <div class="row">
            <div class="col-4" style="background-color: blue; height:100vh">
            </div>
            <div class="col-4" style="background-color: white; height:100vh">
                <div class="row">
                </div>
            </div>
            <div class="col-4" style="background-color: red; height:100vh">
            </div>
        </div>
    </div>
</body>
```

そして、さらに row クラスのブロック要素の中に 3分割 したブロック要素を記述します。

```html:bootstrap.html
<body>
    <div class="container">
        <div class="row">
            <div class="col-4" style="background-color: blue; height:100vh">
            </div>
            <div class="col-4" style="background-color: white; height:100vh">
                <div class="row">
                    <div class="col-4" style="background-color: yellow; height:100vh">
                    </div>
                    <div class="col-4" style="background-color: red; height:100vh">
                    </div>
                    <div class="col-4" style="background-color: black; height:100vh">
                    </div>
                </div>
            </div>
            <div class="col-4" style="background-color: red; height:100vh">
            </div>
        </div>
    </div>
</body>
```

これで完了です。
![スクリーンショット 2020-10-19 5.59.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661269/f7893e31-7d28-eec1-e549-fe820ba6be97.png)
じゃん！！！
【Bootstrap】グリッドシステムは「あれ」ができればマスターできる

さぁ、タイトルが Youtube の動画のタイトルの引きみたいになってしまいましたが、
今回は皆さん、ご存知 Bootstrap についてです:raised_hands_tone1:

世界で最も人気の CSS フレームワーク。
この芸能界の次に入れ替わりが激しいと言われる ITの世界 において、
CSS フレームワーク人気の王座に Bootstrap は、開発当初の 2011年 から座り続けられておられます。

そして人気の大きな理由の一つにグリッドシステムがあります。
そうです、画面サイズによってウニャウニャする、あれです。

簡単にレスポンシブな画面を組むことができるので、
グリッドシステムをマスターすると、できることの幅が相当増えますよね。

グリッドシステムとは一言で説明すると、
画面を横幅のサイズごとに、12分割にし、指定した数字分の範囲を確保する仕組みですね。

この時点で頭が痛くなったデザインに苦手意識がある、そこのサーバーエンジニアのあなた！！
もったいないですよ〜！

それでは、さっそく実践していきましょう！
グリッドシステムを使って、画面を 2分割 にしてみます。

まず、container クラスの block 要素を用意し、その中に row クラスの block 要素を書きます。

```html:bootstrap.html
<body>
    <div class="container">
        <div class="row">
        </div>
    </div>
</body>
```

このように row クラスまで用意することで、グリッドシステムは使用することができます。

さて、画面を 2分割 するには、全部で 12分割 されるうち 6分割分 を 2つ 用意すればOKですね。
6分割分 を確保するには ブロック要素のクラスに col-6 と記述します。

```html:bootstrap.html
<body>
    <div class="container">
        <div class="row">
            <div class="col-6" style="background-color: blue; height:100vh">
            </div>
            <div class="col-6" style="background-color: red; height:100vh">
            </div>
        </div>
    </div>
</body>
```

（分かりやすいように、色を付けて、縦幅をいっぱいにとりました。）

![スクリーンショット 2020-10-19 4.52.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661269/06017179-92e3-c333-419d-d183e589ce30.png)

はい！！！
いやぁ便利ですねぇ〜

続いて、3分割にしてみます。
画面を 3分割 するには、全部で 12分割 するうち 4分割分 3つ を用意すればOKですね。
4分割分 を確保するには ブロック要素のクラスに col-4 と記述します。

```html:bootstrap.html
<body>
    <div class="container">
        <div class="row">
            <div class="col-4" style="background-color: blue; height:100vh">
            </div>
            <div class="col-4" style="background-color: white; height:100vh">
            </div>
            <div class="col-4" style="background-color: red; height:100vh">
            </div>
        </div>
    </div>
</body>
```

![スクリーンショット 2020-10-19 5.02.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661269/35b5c1df-cd3a-5b95-8679-13cf7bcc6a3d.png)

いやぁ便利だなぁ〜。。。

皆さんお気づきでしょうか。。。
Bootstrap のグリッドシステムは、なんと実は。。。
「割り算」ができれば使えてしまうのです！！！

**12 ÷ 画面を何分割したいか = 指定する数字**

となります。（つまり画面を何分割したいか は 12 の約数でなければいけません。）



では最後に、画面を 6分割 しましょう。

12 ÷ 6 = 2 なので、クラスには col-2 を指定すればよいですよね。

```html:bootstrap.html
<body>
    <div class="container">
        <div class="row">
            <div class="col-2" style="background-color: blue; height:100vh">
            </div>
            <div class="col-2" style="background-color: white; height:100vh">
            </div>
            <div class="col-2" style="background-color: red; height:100vh">
            </div>
            <div class="col-2" style="background-color: blue; height:100vh">
            </div>
            <div class="col-2" style="background-color: white; height:100vh">
            </div>
            <div class="col-2" style="background-color: red; height:100vh">
            </div>
        </div>
    </div>
</body>
```

![スクリーンショット 2020-10-19 5.42.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661269/4bab145b-a1a1-0555-4558-0916c4a7e9ca.png)

割り算ができれば、画面の分割ができちゃうなんて、
Bootstrap、ほんとに便利ですねぇ。。。
【PHP】Carbon を使用して日付比較する際の覚え方

PHPer の皆さん、日付の比較どうしてますか〜？

おそらく

・strtotime関数
・DateTimeクラス
・Carbonライブラリ

などを使用されてるかと思います。

ちなみに簡単な日付の比較であれば、文字列のまま比較できることをご存知でしょうか？
まだご存知でない方は、こちらの記事をご覧ください。
https://qiita.com/fusekichi/items/5fa20a37a0220ee879e9

そして私ですが、基本的に **Carbon ライブラリ** を使用しています。

とっっても便利なため、
ここで Carbon ライブラリの使用方法を、
つらつら書き連ねてもよいのですが、

全てこの記事に書いてくれているので、、、
https://qiita.com/yudsuzuk/items/ff894bd0b76d4657741d

今回は Carbon で日付比較する際に、地味に分かりずらい関数の覚え方を、
満を辞して紹介しようと思います。
【JavaScript】3次元のベクトルクラス【HTML5】

#はじめに
自分用の3次元のベクトルクラスです。
ES6で書いています。静的クラスとして書いています。

#ソース
```js
// 3Dベクトルクラス(ベクトルの計算に使用)
class Vector3d {
    // 足し算
    static add(v0, v1) {
        return {
            x: v0.x + v1.x,
            y: v0.y + v1.y,
            z: v0.z + v1.z,
        };
    }
    // 引き算
    static subtract(v0, v1) {
        return {
            x: v0.x - v1.x,
            y: v0.y - v1.y,
            z: v0.z - v1.z,
        };
    }
    // スカラー倍
    static scale(v0, s) {
        return {
            x: v0.x * s,
            y: v0.y * s,
            z: v0.z * s,
        };
    }
    // ベクトルの長さを返す
    static length(v) {
        return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
    }
    // ベクトルの距離を求める
    static distance(v0, v1) {
        const v = Vector3d.subtract(v0, v1);
        return Vector3d.length(v);
    }

    // 単位ベクトルを返す(非破壊的)
    static unit(v) {
        const len = Vector3d.length(v);
        return {
            x: v.x / len,
            y: v.y / len,
            z: v.z / len
        };
    }
    // 内積
    static innerProduct(v0, v1) {
        return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
    }
    // 外積
    static outerProduct(v0, v1) {
        return {
            x: v0.y * v1.z - v0.z * v1.y,
            y: v0.z * v1.x - v0.x * v1.z,
            z: v0.x * v1.y - v0.y * v1.x,
        };
    }
}
```
【Linux】シェルスクリプトでLinux→Windowsへデータコピー

## シェルスクリプトでLinux→Windowsへデータをコピー

#####検証環境
　・CentOS Linux release 7.6
　・Windows Server 2019

#####手順
　1. Linuxにsambaクライアントをインストール

```shell
# sambaクライアントがインストールされているか確認
rpm -q samba-client

# sambaクライアントをインストール
yum install -y samba-client
```

　2. Windowsに共有フォルダを作成
　
　3. Linuxからsmbclientでアクセスしputコマンドでデータをコピー

```shell

# sambaでWindowsの共有フォルダにアクセス
#「smb: \>」と表示されればアクセス成功
#「exit」でsamba接続終了
smbclient '\\WindowsのIPアドレス\共有フォルダ名' -U ドメイン名\\ユーザー名%パスワード
smb: \> put Linuxデータパス Windowsに置くときのファイル名
smb: \> exit
```



## 使用例

```shell

#! /bin/bash
# /var/log配下の.logファイルを全てWindowsの共有フォルダへコピー
for filePath in `find /var/log/*.log`; do

　　　　 # -cでputコマンドを送る
        smbclient '\\WindowsのIPアドレスまたはPC名\共有フォルダ名' -U ユーザー名%パスワード -c "put ${filePath}  ${filePath##*/}"  >&1

        # Linux側のデータが不要の場合は削除する
        rm -f $filePath
done

```
View 疑問　備忘録

## 基礎
参考　https://wemo.tech/79

```html
<!DOCTYPE html>
<html>
    <head>
        <!-- ファイル・スクリプトの読み込みや、様々なメタ情報 -->
    </head>
    <body>
        <!-- 実際に表示される内容 -->
    </body>
</html>
```
## bootstrap
###雛形
https://getbootstrap.jp/docs/4.5/getting-started/introduction/

###グリットシステム
`div class=row`以下に
https://qiita.com/akatsuki174/items/53b7367b04ed0b066bb

###card
bootstrap4以降
https://webnetamemo.com/coding/bootstrap4/201711116162#panels

それ以前はpanelが使用されていた
###form
https://qiita.com/AquaMeria/items/fe3fd9ebeb4c7171da3b

##HTML

###lang属性 書く必要はあまりない
###【HTML】metaタグ：『X-UA-Compatible』
【meta X-UA-Compatible】をわざわざ指定する必要はあまりないかもしれません。
https://www.creativevillage.ne.jp/2819

### nav 
https://style.potepan.com/articles/21440.html

###container 
コンテナ、範囲を定め利用しやすくするため

## csrf
https://qiita.com/wanko5296/items/142b5b82485b0196a2da
ブランチ切り替え時に移動先ブランチのstash一覧を表示させる方法

# stashしたことを忘れてしまう問題

`git stash`は非常に便利ですが、他のブランチで作業をしているうちにstashしたことを忘れ、戻ってきた際に再び同じ作業を始めてしまうようなことがたまにあります。

今回はその対策として、
「ブランチを移動するたびに移動先ブランチのstash一覧を表示するGitフック」
を作成したので、その実装方法について解説します。


### 完成イメージ　
以下のように、移動先ブランチ上でstashしたもののみを表示するイメージです（他のブランチのものは表示しない）。
![スクリーンショット 2020-10-18 0.39.04.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/4cbb03a1-5dcd-b88b-0c69-fb493b6f0e42.jpeg)
これなら明らかに通常と違うため stash の存在を思い出せるはずです。

また、元々存在する機能（git hooks）しか使わないため、変なプラグインを入れたりする必要もありません。

# 実現方法
git の標準機能である git hooks を使います。

git hooksとは`.git/hooks/`下に置かれたスクリプト群のことで、特定のタイミングで自動的に呼び出される仕組みになっているものです。

例えば「commit 前にリントをしたい」という場合には、`pre-commit`という名前のファイルを`.git/hooks/`に配置して、リントを行うコードを書けばOKといった感じです。

今回は`git switch`や`git checkout`の後に呼ばれてほしいので`post-checkout`という名前で作成します。

# 実装

処理の流れを大まかにいうと、
1. `git branch --show-current`で移動後のブランチ名を取得し、
2. そのブランチ名を`git stash list`の中から`grep`する
という感じです。

```zsh:.git/hooks/post-checkout
#!/bin/sh

has_branch_changed=$3 #ブランチ移動したかどうかのフラグ
current_branch=$(git branch --show-current | awk -F/ '{print $NF}')

if [ $has_branch_changed = 1 ] && [ -n "$current_branch" ]; then
  git stash list | grep "$current_branch: "
fi
```

**結果**
![スクリーンショット 2020-10-18 0.34.45.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/57b9f934-3ed6-1389-96f5-5c56310dfb94.jpeg)
※  説明のため、ここではまだ文字色の変更等は行っていません。色付きバージョンのコードは次節をご参照ください。

##### 技術的な詳細

- `git checkout`してもブランチが変わっていないケースもあるため、`post-checkout`の三番目の引数`$3`（ブランチ移動したかどうかのフラグ）を使ってチェックを入れています。ちなみに`$1`には移動元のcommit hash, `$2`には移動先のcommit hashが入っています。

- `awk -F/ '{print $NF}'`はブランチ名を`/`で分割して末尾部分を取得するコードです。この処理が必要なのは、ブランチ名が`/`で区切られている場合`git stash list`は区切りの末尾の部分しか表示しないためです。例えば`aaa/bbb/ccc`なら`ccc`の部分しか表示しないため、単純に`grep <ブランチ名>`では取得できません。

- `[ -n "$current_branch" ]`でブランチ名が1文字以上かのチェックを行っていますが、これは detached HEAD の場合ブランチ名が出力されず、結果的に全ての stash が表示されてしまうためです。

# もっと目立たせる

上記のコードでは文字色の変更等は行っていませんでした。
しかしより視認性を高めるためには`echo`を通して文字色を変更したほうが良いかもしれません。

```bash:.git/hooks/post-checkout
#!/bin/sh

has_branch_changed=$3 #ブランチ移動したかどうかのフラグ
current_branch=$(git branch --show-current | awk -F/ '{print $NF}')

if [ $has_branch_changed = 1 ] && [ -n "$current_branch" ]; then
  git stash list | grep "$current_branch: " | while read line; do
    echo "🐿   \033[32m$line\033[m"
  done
fi 
```

**結果**
![スクリーンショット 2020-10-18 0.39.04.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/e53da835-2a54-bd26-53b0-1b2df9176c47.jpeg)
前節のコードの出力を`while read`で回して、`echo`で色と絵文字を付加しているだけです。

※ **`echo`の文字色の変更法はシェルによって異なります。**例えば bash の場合は`-e`オプションが必要かと思います。より詳しくは[こちらの記事](https://qiita.com/ko1nksm/items/095bdb8f0eca6d327233#%E7%B5%90%E8%AB%96)をご参照ください。

以上です。改善点等があればコメントやリクエストからご教示いただけると幸いです。
Pythonでライブラリの中身まで入ってデバッグテストする設定

# はじめに

この記事はpytestの利用が中心に書かれていますが、Pythonを使ったプログラミング全般に応用できる内容になっています。ぜひ最後までお付き合いください。

# あらすじ

pytestやunittestなどのテストをしていて、テストコードのデバッグが必要になったとします。それでステップ実行してオブジェクトの中身を逐次網羅的に確認していくとします。

そんな時、自分のコードだけのステップ実行では問題が解決しないことがあります。そうすると、インストールしたライブラリの中までデバッグしたい場合があります。しかし、デフォルトでは自分のコード以外はステップ実行の範囲外となって、そこで起きているエラーしか表示されません。何故エラーなのか分からなくて困ってしまいます。

以下の設定をすれば、`pip`などでインストールしたライブラリ内にブレークポイントを設定することもできます。

ただし、C言語で実装されたライブラリは本記事の末尾で紹介する参考ページのような方法が必要です。

# 通常のデバッグの場合

デバッグテストではなく、通常のデバッグのときには、
[VSCodeでライブラリの中身まで入ってデバッグする設定](https://qiita.com/timtoronto634/items/799e6eea4fd9bb30f023)をご覧いただくといいと思います。

# 普段の設定

普段は、vscodeでデバッグしているとき、`launch.json`は以下の設定になっていることが多いと思います。

```json-doc:launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal"
        }
    ]
}
```

# デバッグテストで他者のライブラリに潜る設定

"request"が"test"になっている構成があると、デバッグテストのときに使用されます。

また、この構成は、最初の１つだけが読み込まれます。
以降に同様の構成があると無視されます。

この構成に`justMyCode`があり、「**自分のコードだけ**」か切り替えることが出来ます。

```diff_jsondoc:launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal"
        },
        {
            "name": "Debug Tests",
            "type": "python",
            "request": "test",
            "console": "integratedTerminal",
+           "justMyCode": false
        }
    ]
}
```

もちろん、元に戻すときには、追加した行を消すだけでOKです。

# C言語で実装されたライブラリの場合

混合モード デバッグ機能と言って、[Python と C++ を同時にデバッグする](https://docs.microsoft.com/ja-jp/visualstudio/python/debugging-mixed-mode-c-cpp-python-in-visual-studio?view=vs-2019)方法がVisual Studioで提供されています。
VScodeでも、[Python と OpenCV を混合でデバッグ（ステップ実行）する方法](https://daeudaeu.com/opencv_debug/)を参考にして各種ライブラリをデバッグすることが可能です。

**Excelsior!**
UnityでiOS向けにC系の関数を扱う

# 概要
UnityからC言語を使う為の備忘録です。

# 参考
https://docs.unity3d.com/ja/2018.4/Manual/NativePlugins.html

# 実装
## 名前空間
```
using System.Runtime.InteropServices;
```
[DllImport("__Internal")] を使用するのに必要です。

## 属性
```
[DllImport("__Internal")] 
```
メソッドの上に書く。

### サンプル
```
/// <summary>
/// 初期化
/// </summary>
[DllImport("__Internal")]
static extern void InitializeiOS(string hogehoge);
```
iOSでしか機能しないので「UNITY_IOS」などのシンボルを活用すると尚良い。

## C

```
extern "C"
{
    void InitializeiOS(char *hoge)
    {
        // 処理
    }
}
```
 stringはcharのポインタで。

## 設置方法
基本的には「Assets/Plugin/iOS/XXXXX.mm」としてファイル名をつけて保存する。
ビルドするとそのままXcodeプロジェクト内部に保存される。
EnOceanとNode-REDとobnizでトイレセンサー作ってみた

obnizのNode-REDが新しくなったみたいなので、初めてobnizに触れてみました。
https://qiita.com/wicket/items/e150e78cd787da03493e

EnOceanのドア開閉センサーを使ってドアの開閉状態をobnizで可視化してみました。

![IMG_2034.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/4408fb3a-9116-603a-b134-5824f8ffaf92.png)
[ドア開閉センサー](https://www.switch-science.com/catalog/2549/)

# デモ動画
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/WZSnL-t9K1k/0.jpg)](http://www.youtube.com/watch?v=WZSnL-t9K1k)

# システム構成
Node-REDを使ってシンプルに作成しました。

![スクリーンショット 2020-10-19 11.13.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/d99445df-7066-8928-448d-99acd4cabe34.png)

## EnOceanの設定
Node-REDでEnOceanを使う場合は下記サイトの1を行うと使うことができます。
https://qiita.com/h-takauma/items/e81f46c9170fed1baa18

## EnOceanデコーダー
EnOceanのUSBから送られてくるデータは専用デコーダーを公開しておりますので、
ノード追加から `node-red-contrib-enocean-telegram-decoder` を検索して追加してみてください。

https://flows.nodered.org/node/node-red-contrib-enocean-telegram-decoder

![スクリーンショット 2020-10-19 11.11.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/98a64298-ca2d-d838-da16-0cb1330ebef3.png)

## 開閉操作
使用したセンサーから送られてくるデータは、「09」が閉まっている状態、「08」が空いている状態だったので、
switchノードを使って切り分けました。

![スクリーンショット 2020-10-16 13.59.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/b93fc701-fc42-c7bd-4a8c-3a924dc63888.png)

## obniz設定
obnizの具体的な設定は先程のサイトに詳しく書かれています。
obniz-functionノードにobnizの設定とコードを記載しました。単純に「使用中」か「空室」どうかを切り替えています。

```javascript:obniz-functionコード
obniz.display.clear();
obniz.display.setColor('red');
obniz.display.pos(5,10);
obniz.display.font(null,50)
obniz.display.print("使用中")
```
![スクリーンショット_2020-10-16_14_01_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/8a314767-5fcc-a86d-7a6e-86fa7fc91303.png)

センサーがドアに近づくと「使用中」に、離れると「空室」に切り替わります。

![スクリーンショット 2020-10-16 14.06.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/5f677d2c-9dbe-c0aa-4394-e5c8d3fbb057.png)

### まとめ
obnizに初めて触れてみましたが、あっという間に実装できて、Node-REDと簡単に連携できてしまったので驚きました。
M5StickCもコンパクトにまとめられたデバイスなので、すぐにIoTを始めることができますね。

システム化のご検討やご相談は弊社までお問い合わせください。
https://i-enter.co.jp/contact/
__name__について簡単に

## __name__

実行しているコードでは、__ name __ =' __ main __ 'が入る
import されたファイルの内部では、__ name __ ='ファイル名'が入ってる
これを区別する事で、どのファイルを実行しているかが分かる
従って、mainファイルを他のファイルで呼び出した時に、main()は実行されない仕組みが作れる

## 具体例

#### bファイルにif __name__ == '__main__':がない場合

```b.py
def import_print_name():
  return __name__

print(import_print_name())
```

```main.py
import b

def main():
  print("importしたファイル名になる。今回の場合",b.import_print_name())
  print(__name__)

if __name__ == '__main__':
  main()
```

```実行結果（mainを実行）.
b
importしたファイル名になる。今回の場合 b
__main__
```
上記bは、import bの時点で呼び出される

#### bファイルにif __name__ == '__main__':がある場合

```b.py
def import_print_name():
  return __name__

if __name__=='__main__':
  print(import_print_name())
```

```main.py
import b

def main():
  print("importしたファイル名になる。今回の場合",b.import_print_name())
  print(__name__)

if __name__ == '__main__':
  main()
```

```実行結果（mainを実行）.
importしたファイル名になる。今回の場合 b
__main__
```
Xplenty : Google Sheetからデータを取得する

このブログではXplentyのRest API Componentを使用して、Google Sheetからデータを読み込む方法について解説します。

#Rest API コンポーネントの設定

##認証（Authentication）の設定
あらかじめ接続画面で作成したGoogle Sheetの認証を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/fd21ab82-8229-6fcb-3593-8e09f464d39a.png)


##URLの指定方法

**URL:** 
`https://sheets.googleapis.com/v4/spreadsheets/シートID/values:batchGet?ranges=セル範囲&majorDimension=ROWS`

- **シートID:**
Google SheetのURLからシートIDを取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/dbede37c-87f6-b07f-6f58-ab39d5e2d0a2.png)

- **セル範囲:**
例）A1:G1000 (A列の1行目からG列の1000行目まで）

##Responseの設定
「$..values[*]」と入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/b0c0c1a8-4269-cc83-2d55-b641deab91a7.png)

##フィールドの選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/77e2a8a9-5b59-c28c-12f2-00b38a47bd41.png)

#取得したJSONのフラット化
##変換1:BAG型からTuple型に変換する
Selectコンポーネントを使用し、BagToTuple関数を使いTuple型に変換する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/1ed9b948-d34e-6c28-e478-8d20ff65c887.png)

##変換2:各列を配列番号を指定し、それぞれ取得する
それぞれの列を配列番号（$0）を指定し取得するとともに、Chararray関数で文字列型に変換する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/2f153957-a4f1-2ad7-2b67-87196c5ed5b0.png)

##ヘッダ行をフィルターで除外
1行目にヘッダ行が含まれている場合、フィルタで除外する（Rest API側のセルの範囲指定でヘッダ行を除外する方法もあり。）
（例）id列に「Id」という文字が含まれていないデータのみ抽出
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/d77c18a7-4658-a5fa-0bed-32ecea5c4b49.png)

#ロード先のコンポーネントをセットし、ジョブを実行して確認
最後にデータベース、DWH、ストレージなどにロードすれば完了です。
##パッケージ全体図
例）Snowflakeがロード先の場合、以下のようなフローになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/e9a88bf9-889f-4bd2-ff95-c21f8dd2304c.png)

##データが正しく反映されたことを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/1ab098c3-9b58-27e0-4501-f8311da44561.png)

#Google Sheetへの書き込みも可能です
Xpelntyでは、Selectコンポーネントの中でCurlリクエストを書くことで、Google Sheetへの書き込みが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/a2e021fc-2d0d-9f7a-4d74-b25d82364f5b.png)

**書き込みリクエスト例：**
`CCurl(CONCAT('https://sheets.googleapis.com/v4/spreadsheets/', '$spreadsheetId', '/values:batchUpdate'),'POST','{"Accept":"application/json"}',CONCAT('{"valueInputOption":"RAW","data":[{"range":"','$range','","majorDimension": "ROWS","values": [', BagToString(data, ','), ',]}]}'), '$connection_id')`

**上記リクエストで使用している変数について**

- `$spreadsheetId`：GoogleSheetのIDを指定
- `$connection_id`：XplentyのコネクションIDを指定 （コネクション画面で確認することができます。）
例：GOOGLESHEETS_CONNECTION_9215
- `$range`：シート名およびセル範囲を指定。
例：campaign!A1:N100000
Kerberos协议之AS_REQ & AS_REP

# 简述Kerberos
Kerberos是一种由MIT（麻省理工大学）提出的一种网络身份验证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证。

在Kerberos协议中主要是有三个角色的存在：

1. 访问服务的Client(以下表述为Client 或者用户)
2. 提供服务的Server(以下表述为服务)
3. KDC（Key Distribution Center）密钥分发中心 kerberos 测试工具介绍

其中KDC服务默认会安装在一个域的域控中，而Client和Server为域内的用户或者是服务，如HTTP服务，SQL服务。在Kerberos中Client是否有权限访问Server端的服务由KDC发放的票据来决定。

kerberos的简化认证认证过程如下图
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/4bd27682-030a-578e-0714-0fae3534032e.png)

1. AS_REQ: Client向KDC发起AS_REQ,请求凭据是Client hash加密的时间戳
2. AS_REP: KDC使用Client hash进行解密，如果结果正确就返回用krbtgt hash加密的TGT票据，TGT里面包含PAC,PAC包含Client的sid，Client所在的组。
3. TGS_REQ: Client凭借TGT票据向KDC发起针对特定服务的TGS_REQ请求
4. TGS_REP: KDC使用krbtgt hash进行解密，如果结果正确，就返回用服务hash 加密的TGS票据(这一步不管用户有没有访问服务的权限，只要TGT正确，就返回TGS票据)
5. AP_REQ: Client拿着TGS票据去请求服务
6. AP_REP: 服务使用自己的hash解密TGS票据。如果解密正确，就拿着PAC去KDC那边问Client有没有访问权限，域控解密PAC。获取Client的sid，以及所在的组，再根据该服务的ACL，判断Client是否有访问服务的权限。

本文注重前两个

# AS_REQ
用daiker师傅的工具来发Kerberos包。

配置域账户
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/1aff1f2f-2986-7d88-dd07-c3af837465cb.png)

勾上`PAPAC_REQUEST`、`ENCTIMESTAMP`、`etypes`里的`rc4hmac`加密。发包

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/f6f6700c-dbbe-4ecd-2ccf-3e3c770452ff.png)

抓包可见两个请求包AS-REQ AS-REP
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/85e201b1-aa32-05cb-1bed-792e07e5bf24.png)

AS-REQ中各个字段
1. pvno Kerberos版本
2. msg-type Kerberos类型 0x0a对应krb-as-req
3. padata 存放了PA-ENC-TIMESTAMP和PA-PAC-REQUEST
3.1 PA-ENC-TIMESTAMP是预认证，使用用户hash加密时间戳，AS存放了用户的hash，AS用用户hash解密获得时间戳。如果时间戳在某一个时间则认证成功。
3.2 PA-PAC-REQUEST是微软引入的PAC拓展，include-pac=true，KDC会根据include的值来判断返回的票据中是否携带PAC。
4. req-body
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/33a02077-0f2b-4807-261e-91a3f60c209a.png)
4.1 cname
PrincipalName 类型。PrincipalName包含type和value。
KRB_NT_PRINCIPAL = 1 意思是只用用户名就行，比如`admin@test.local`这个域用户，只需要填admin
KRB_NT_SRV_INST = 2 service and other unique instance (krbtgt) 这个一般指服务账户名
KRB_NT_ENTERPRISE_PRINCIPAL = 10 `admin@test.local`用户全称。
4.2 sname PrincipalName 类型 在AS_REQ里面sname是krbtgt，类型是KRB_NT_SRV_INST
4.3 till 到期时间
4.4 nonce 随机数
4.5 etype hash加密类型

# AS-REP
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/779b9952-c190-8091-ae35-04cf6f1854f3.png)

KDC使用用户hash解密，如果结果正确返回用krbtgt hash加密的TGT票据。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/a19226a2-5be3-189c-ab08-55f438188efb.png)

各个字段的含义
1. msg-type krb-as-rep 对应的是0x0b
2. crealm 域名
3. cname 用户类型和用户名
4. ticket tgt票据 这里存在黄金票据的问题，因为返回的tgt是通过krbtgt的hash加密的，如果知道krbtgt的hash，则可以伪造任意用户。
5. enc-part 这部分可以用daiker师傅的工具解密。key是用户hash，解密后得到Encryptionkey。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/86399362-c950-4d63-fdf2-0c4a74cad4b3.png)

# 参考
1. https://daiker.gitbook.io/windows-protocol/kerberos/1
2. https://github.com/daikerSec/windows_protocol/tree/master/tools

吹爆daiker师傅
db:maigrate:resetでエラー

##rails db:maigrate:resetがエラーになったとき

**環境**
Rails 5.2.4.4

**エラー内容**
rails db:migrate:resetをした時に`Text file busy @ apply2files`のエラーが出た。


**解決法**
`rails db:reset`は

```
$ rm db/development.sqlite3
$ bin/rails db:setup
```



`rails db:migrate:reset`は

```
$ rm db/development.sqlite3
$ bin/rails db:create db:migrate
```

それぞれこちらで実行できました。
windows環境で起きることがあるみたいです。
iOS14(xcode12ビルド)で、WKWebView の contentInset.top を一定値以上セットすると webView の load 中になぜか最下部までスクロールされる バグ？


iOS14+xcode12によるビルドでバグのような挙動が発生しているので報告です


**WKWebView の contentInset.top を一定値以上セットすると、
webView の load 中になぜか最下部にスクロールされる**

というものになります。

一定値というのは700〜800あたりで発生することを確認してます
500とかだと発生しません



以下再現コードです
WKWebViewを全面に配置しただけのstoryboardもあらかじめ作ってあります

```swift

class ViewController: UIViewController {
    @IBOutlet weak var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let url = URL(string: "https://cookpad.com")!
        
        let request = URLRequest(url: url)
        
        webView.load(request)
        
        webView.scrollView.contentInset.top = 800.0

        DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
            self.webView.reload()
        }
    }
}
```

実行すると、なぜか最下部までスクロールした状態でロードされます。
リロード後も同じ。

例：
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48695/b9014149-bb77-6013-efa9-303d32e102d6.png width=300>



しかし、軽いページなのかなにか条件があるのか、一度目はちゃんと最上部のままロードされるページもあります
（google.co.jp等）
ただ、その場合も `reload()` 後は最下部にスクロールされた状態になります


iOS14SDKのバグっぽい挙動なのですが、報告です

もし回避策がありましたら教えていただけるとありがたいです！
PHP8.0のJITコンパイラはFFIにどこまで追いつけるか？

# はじめに
以前このような記事を投稿しました

[PHP7.4の新機能、FFIでGoを使ってみた
https://qiita.com/i4M1k0SU/items/7c0db12e047e0fbf7550](https://qiita.com/i4M1k0SU/items/7c0db12e047e0fbf7550)

この記事ではPHP7.4での新機能、FFIからGoで実装した共有ライブラリを利用し、FFIを利用しない場合と比べ20倍以上ものパフォーマンスを出すことができました

今回はPHP8.0に追加された新機能、 `JITコンパイラ` を利用し、この結果にどこまで追いつけるかを検証します

# PHP8.0の導入
PHP8.0はこの記事を投稿した段階ではまだ正式なリリースがされていません

今回はmacを利用しているのですが、DockerやVMは使わずhomebrewからネイティブ環境に導入することにしました

https://github.com/shivammathur/homebrew-php


```bash
brew update
brew tap shivammathur/php
brew install shivammathur/php/php@8.0
brew link --overwrite --force php@8.0
```

## JITコンパイラの有効化
php.iniを書き換えます
設定値の詳細については他の方の記事をご参照ください
調整次第でパフォーマンスに変化があるのかもしれませんが、今回の記事は以下の値を利用します

```/usr/local/etc/php/8.0/php.ini
opcache.enable=1
opcache.enable_cli=1
# 以下は追記する必要があります
opcache.jit=1235
opcache.jit_buffer_size=128M
```

# JITコンパイラでPHPはどれだけ速くなるか

[以前書いた記事](https://qiita.com/i4M1k0SU/items/7c0db12e047e0fbf7550#ffi%E3%81%A7php%E3%81%AF%E3%81%A9%E3%82%8C%E3%81%A0%E3%81%91%E9%80%9F%E3%81%8F%E3%81%AA%E3%82%8B%E3%81%8B)と全く同じ検証用コードです
フィボナッチ数列を40番目まで求めます
再帰を使っていて数が大きくなるほど計算に時間がかかるサンプルです

また、ついでにPHP8.0+FFIも検証します

```php
const COUNT = 40;

$ffi = FFI::cdef(
    'extern unsigned int calcFibonacci(unsigned int p0);',
    '[PATH]/fibonacci.dylib'
);

// 比較対象のPHP実装サンプル
function calcFibonacci(int $i): int {
    if ($i < 2) {
        return $i;
    }

    return calcFibonacci($i - 1) + calcFibonacci($i - 2);
}

// Go(FFI)実装の実行速度計測
$startTime = microtime(true);
for($i = 1; $i <= COUNT; $i++) {
    $ffi->calcFibonacci($i);
}
$time = microtime(true) - $startTime;
echo "Go(FFI): {$time} 秒\n";

// PHP実装の実行速度計測
$startTime = microtime(true);
for($i = 1; $i <= COUNT; $i++) {
    calcFibonacci($i);
}
$time = microtime(true) - $startTime;
echo "PHP: {$time} 秒\n";
```

# 結果

小数第三位を四捨五入しています

|                | FFI 利用           | PHP のみ            | 
| -------------- | -----------------: | -----------------: | 
| **[PHP7.4 (前回の結果)](https://qiita.com/i4M1k0SU/items/7c0db12e047e0fbf7550#%E7%B5%90%E6%9E%9C)**     | **1.58 秒** | 33.62 秒 | 
| **PHP8.0 without JIT (and opcache)**     | 1.86 秒 | 42.44 秒 | 
| **PHP8.0 with JIT** | 1.96 秒 | **9.50 秒** |

良い結果が出たのではないでしょうか

気になる点として、PHP8.0は何もしなくてもPHP7.4より速くなると言った内容の記事もありましたが、私の環境ではJITコンパイラ無効時はPHP7.4より遅くなっているようです
また、FFI利用時は誤差レベルかもしれませんがJITコンパイラの設定に関係なく、少し遅くなっているようです

とは言ってもJITコンパイラを有効にした場合の結果はとても優秀で、FFIに追いつきこそはしませんが、かなり大きな速度向上が見込めるのではないでしょうか
また、FFIとは異なり、PHP以外の言語で実装する必要なく、そのまま高速化できる点も大きなメリットではないでしょうか

設定を有効にするだけでここまでの高速化が可能なので、積極的に利用していきたい機能です
プロダクトバックログ

## プロダクトバックログ

- スクラムの成果物（アーティファクト）の一つ
- プロダクトに必要なものを順番に並べた一覧
- POが内容、可用性、並び順に責任
- PBI（プロダクトバックログアイテム）

---
### プロダクトバックログの内容

- 詳細・並び順・見積り・価値の属性
- テストも含まれる
- プロダクトが存在する限り、プロダクトバックログも存在し続ける（プロダクトが改善しつづける）

---
## 並び順
- 上部にあるものが優先
- not 優先度, 優先順
- 優先順位が高いものほど明確で詳細
- 高いものほど見積もりされやすい

---
## デイリー
- 昨日行ったこと
- 今日行うこと
- 困っていること


---


## 参考

https://junhiguchi.hatenablog.jp/entry/20190725/1564015238

---
Scrum Guide 2017

https://www.scrumguides.org/docs/scrumguide/v2017/2017-Scrum-Guide-Japanese.pdf

プロダクトバックログ
プロダクトバックログは、プロダクトに必要だと把握しているものをすべて順番に並べた一覧である。
プロダクトに対する変更要求の唯一の情報源である。プロダクトオーナーは、プロダクトバックログ
の内容・可用性・並び順に責任を持つ。
プロダクトバックログは決して完成しない。構築の初期段階には、明確でよく理解できている要求
が並べられている。その後、プロダクトや使用環境に合わせて進化する。プロダクトバックログは動
的であり、適切で競争力のある有用なプロダクトに必要なものを求めて絶えず変化する。プロダク
トが存在する限り、プロダクトバックログも存在し続けるのである。


プロダクトバックログは、今後のリリースで実装するプロダクトのフィーチャ・機能・要求・要望・修正
をすべて一覧にしている。プロダクトバックログアイテムには、詳細・並び順・見積り・価値の属性が
ある。プロダクトバックログアイテムには、「完成」時にそれを確認するためのテスト記述も含まれて
いることが多い。

プロダクトが使用されて価値が増加し、市場からフィードバックを得られると、プロダクトバックログ
は巨大で包括的な一覧になる。要求の変更は止まらない。プロダクトバックログは生きた作成物で
ある。ビジネス要求、市場の状態、技術の変化などが、プロダクトバックログの変化につながる。
複数のスクラムチームが同じプロダクトの作業をすることがよくある。そうした場合、プロダクトの作
業は 1 つのプロダクトバックログに記述する。また、アイテムを分類するための属性をプロダクトバ
ックログに追加することもある。
プロダクトバックログに含まれるアイテムに対して、詳細の追加、見積り、並び替えをすることを、プ
ロダクトバックログのリファインメントと呼ぶ。これはプロダクトオーナーと開発チームが協力して行う
継続的なプロセスである。プロダクトバックログのリファインメントによって、アイテムのレビューと改
訂が行われる。いつどのようにリファインメントをするかは、スクラムチームが決定する。リファインメ
ントは、開発チームの作業の 10%以下にすることが多い。ただし、プロダクトバックログアイテムは
プロダクトオーナーの判断によって、いつでも更新できる。
並び順が上のプロダクトバックログアイテムほど明確で詳細である。明確で詳細であれば、見積り
も正確になる。並び順が下のアイテムほど不正確で詳細ではない。今後のスプリントで開発チーム
が従事するプロダクトバックログアイテムは、スプリントのタイムボックスで「完成」できるようにうまく
細分化する。開発チームが 1 つのスプリントで「完成」できそうなプロダクトバックログアイテムは、ス
プリントプランニングで選択できる「準備完了（Ready）」の状態になったと見なすことができる。プロ
ダクトバックログアイテムは、上記のリファインメントによって透明性を獲得することが多い。
開発チームは見積りに対して責任を持つ。プロダクトオーナーがトレードオフの理解や選択などに
ついて開発チームに影響を及ぼすこともあるが、最終的な見積りは実際に作業をする人が行う。
pryでparamsの中身を確認する

## 背景
記事詳細を表示する際に、ユーザー名を表示したかったが、どこに格納されているのかわからず、paramsの中身を調べることにした。その過程のログを残しておく。

dockweの場合は、これを参考
https://qiita.com/terufumi1122/items/64533b9ddac9941b59e4

### やり方
gemをインストール　(gem 'pry-rails')
↓
bundle install
↓
調べたい該当箇所に、binding.pryを入力。
↓
rails s
↓
該当箇所をブラウザでぽちぽち。ターミナルに、入力した箇所で止まったログが表示される。
↓
そして、[1] pry(#<PostsController>)>
と表示されるから、そこに知りたい文字列を入力。


```ruby:qiita.controller.rb

    12: def show
    13:   #一つの投稿のみを取得したい。
    14:   @post = Post.find(params[:id])
 => 15:   binding.pry
    16: end
```

試しに上から順に、
id
params[:id]
@post.content
@post.user
と入力してみた！

```shell

[1] pry(#<PostsController>)> id
NameError: undefined local variable or method `id' for #<PostsController:0x00007f9f26ea4828>
from (pry):1:in `show'

[2] pry(#<PostsController>)> params[:id]
=> "1"

[3] pry(#<PostsController>)> @post.content
=> "Temporibus vel ratione aperiam alias aut libero reiciendis voluptatem quo autem rerum doloribus adipisci a voluptas modi illo qui ipsum aliquid voluptatum nventore at esse maiores ut omnis accusantium animi ducimus qui autem architecto excepturi itaque ex minus facere soluta inventore molestias id unde vero sunt aliquam quia dolorum quae placeat deserunt aspernatur qui suscipit quod dolorem maxime nulla id molestiae incidunt aut beatae aut voluptate aliquid dicta velit sit sint eum possimus nihil non voluptatem provident enim assumenda consequatur fugiat."

[4] pry(#<PostsController>)> @post.user
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ (pry):4:in `show'
=> #<User:0x00007f9f26c77b68
 id: 1,
 name: "swifty_kazu",
 email: "hogehogehoge",
 created_at: Fri, 16 Oct 2020 02:53:43 UTC +00:00,
 updated_at: Fri, 16 Oct 2020 02:53:43 UTC +00:00,
 password_digest: [FILTERED],
 admin: true>

[5] pry(#<PostsController>)> @post.user.name
=> "swifty_kazu"

[6] pry(#<PostsController>)> 

```


exit!で抜け出せる

参考記事
https://qiita.com/tomoharutt/items/6b12af3dc5eb8dfb9801
https://pikawaka.com/rails/params#params%E3%81%AE%E4%B8%AD%E8%BA%AB%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86
https://qiita.com/k0kubun/items/b118e9ccaef8707c4d9f
Windows10 システムファイル修復方法

# 前提
* Powershell 管理者権限で動かす

ログをリアルタイムで確認しながらやると良い

```
get-content -wait -tail 10 C:\Windows\Logs\CBS\CBS.log
```




# 正常性確認
## コンポーネントストアの確認

```
dism /online /cleanup-image /checkhealth
```
を実行して

```
コンポーネント ストアが壊れていることは検出されませんでした。
操作は正常に完了しました。
```
が出力されれば問題ない。


## システムファイルの確認

```
sfc /verifyonly
```
を実行して

```
Windows リソース保護は、整合性違反を検出しませんでした。
```
が出力されれば問題ない。
最近のSSDのマシンだと10分以下で終わるはず。


# 修復方法
## コンポーネントストアの修復

scanhealth, restorehealth をより短い時間で終わらせるために、不必要なコンポーネントストアを減らす。
これを実施すると、FU，QU をアンインストールできなくなるが、大抵の場合問題ない。

```
dism /online /cleanup-image /startcomponentcleanup /resetbase  

操作は正常に完了しました。  
```

その後、

```
dism /online /cleanup-image /scanhealth
```
を実行して

```
コンポーネント　ストアは修復できます
```
が出力されるはず。これが出力されない場合は、windowsupdate 等が正しく動作していない。
CBS.log を確認し対処する。
修復できることを確認せず、 restorehealth を実施すると、更におかしなことになる。 



```
dism /online /cleanup-image /restorehealth

復元操作は正常に完了しました。
操作は正常に完了しました。
```

## システムファイルの修復

```
sfc /scannow
```

```
破損したファイルを検出しましたが、その一部を修正できませんでした。
```

が出力された場合は、再起動後、コンポーネントストアの修復、システムファイルの修復をもう一度行う。
修復された場合は

```
破損したファイルが見つかりましたが、それらは正常に修復されました。
```

が出力された場合は、再起動し、コンポーネントストアの確認、システムファイルの確認を実施する。


```
Windows リソース保護は、整合性違反を検出しませんでした。
```

が出力された場合は、システムファイルは壊れていない。
php artisan コマンド　備忘録

##コントローラー作成

`php artisan make:controller XxxController`でも十分だが、


```Laravel
php artisan make:controller XxxController --resource
```

の方が、登録・更新・参照・削除など必要なメソッドを用意してくれるため作業速度が上がるぞ。

## Migration・Modelの作成
個別に作成しても問題ないが、名前をつける手間・ミスなどをなくすためにもなるぞ。

```laravel
php artisan make:model Xxx --migration
```
Azure App Service で Azure AD 認証を有効化する

　Azure App Service のシンプルな Web ページで Azure AD 認証を有効化する際の手順の記録です。シークレットキーを用いた Web API アクセスではなく、ブラウザでユーザー認証を受けるシンプルなシナリオを想定します。マルチテナントのシナリオは [Microsoft Docs (Manage identity in multitenant applications)][1] により詳しい説明があります。

[1]: https://docs.microsoft.com/azure/architecture/multitenant-identity/

### 前提条件

* Azure Active Directory のテナントは既に作成されているものとします
* サブスクリプション、リソースグループ、リソースに対する適切な権限があるものとします
* App Service Plan および App Service は既に作成されているものとします
* Azure AD アプリを新たに作成する場合、その権限があるものとします

### 手順

1. 対象の App Service を選択して **認証/承認 (Authentication / Authorization)** のブレードを開きます
2. 「App Service Authentication」で **On** を選び、「認証プロバイダー (Authentication Providers)」では **Azure Active Directory** を選択します
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/04431cf0-7a0f-bf26-44bd-a51606f7e812.png)
3. App Service と AD アプリと関連付けます。既にある AD アプリを使用せず、新しく作成する場合「管理モード (Management mode)」は **簡易 (Express)**、**Create New AD App** を選び、AD アプリの名前を入力します
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/2acb4765-591a-e57f-4417-972dd3359690.png)
   同一のテナントに既に存在するADアプリを使用する場合は Select Existing AD App から対象のアプリを選びます。異なるテナントに存在するマルチテナント認証の AD アプリを使用する場合は「Advanced」の画面から client id と issuer url を入力します
4. OK ボタンで前の画面に戻り、保存します。認証のないリクエストを受けたときにログインへ誘導させる場合（つまり、未認証のアクセスを許可しない場合）は「要求が認証されない場合に実行するアクション」に **Azure Active Directory でのログイン** を選択します
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/191c591f-6b9b-94c5-5d9b-e049cd273206.png)
5. 上記の構成を保存すると App Service にアクセスしたときに認証を求められるようになります
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/922b1cbb-3a83-7ee3-48bf-fc4771eb2d3f.png)
6. 登録した AD アプリには「リダイレクトURI」が設定されていること、暗黙的な許可 (Implicit grant) の「ID トークン」がオンになっていることを確認します。この例でリダイレクト URI は `https://{APP_SERVICE_DOMAIN}/.auth/login/aad/callback` となっています
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/9f525762-e5e5-bdc7-2d72-d2c30d905607.png)

ASP.NET Web アプリケーション (.NET Framework) と App Service を使用している場合 Web サーバー環境変数 [Request.ServerVariables][2] で認証タイプ、ユーザー名の情報を取得できます

| サーバー環境変数 | 説明 |
|:--|:--|
| ServerVariables["AUTH_TYPE"] | ユーザーの認証方法が設定される。AD認証の場合 `aad` となる |
| ServerVariables["AUTH_USER"] | ユーザーの名前が設定される。例えば `*@*.onmicrosoft.com` 等 |
| ServerVariables["AUTH_PASSWORD"] | Basic認証の場合にダイアログに入力された値が設定されるとのこと。AD認証では使用されない |
| ServerVariables["LOGON_USER"] | Windows 認証の場合に Windows アカウント名が設定されるとのこと。AD認証では AUTH_USER と同じユーザー名が設定される |
| ServerVariables["REMOTE_USER"] | ユーザーから送信されたマップされていないユーザー名とのこと。AUTH_USER と同じユーザー名が設定される |
| Request.IsAuthenticated | 認証されているかを表す真偽値 |

[2]: https://docs.microsoft.com/ja-jp/dotnet/api/system.web.httprequest.servervariables
Unity対応のマージツールを比較する

# はじめに
チーム開発ではバージョン管理システム及びマージツールは必要不可欠です。
私は普段の開発ではVSCode+GitLensを使用することが多いのですが、Unity純正のバージョン管理システムであるUnity Collaborateを使って開発する機会ができたため、この機会にUnity対応のマージツールを探します。

MacだとApple File Mergeがあるので、今回はWindows対応のものを探します。

# 前提
要件は、Unity側で対応していること、無料であること、Windowsで使えること。
用途はUnity Collaborateでのソースコードの比較です。

（マージツールの説明については[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%BC%E3%82%B8_(%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0))を参照してください。）

# 比較対象
Windows版のUnityが対応している比較/マージツールは以下の７種。

* SourceGear DiffMerge
* TkDiff
* Araxis Merge
* TortoiseMerge
* WinMerge
* PlasticSCM Merge
* Beyond Compare 4

その中で無料で使用できるのは

* SourceGear DiffMerge 
* TkDiff
* TortoiseMerge
* WinMerge

の４つでした。
（PlasticSCM Mergeはライセンスによって値段が変わり、個人、非営利団体、及びオープンソース開発には無料で用いることができますが、今回は外します）

# 簡易比較

今回の結果の表です。簡易的に比較します。情報量の多さの参考としてGoogle検索結果の見積もり件数（2020/10/19現在）を載せました。

| マージツール | Google検索結果の見積り数 | セットアップの大変さ | Windows以外のOS | 使用感（個人の意見）|
|:--|--:|:-:|:-:|:-:|
| (SourceGear) DiffMerge  | 約 440,000 件  | 簡単 | 対応 | シンプル |
| TkDiff  | 約 77,700 件 | 大変 | 対応 | （未使用）|
| TortoiseMerge | 約 30,300 件 | やや大変 | 非対応 | 使いやすい |
| WinMerge | 約 501,000 件 | 簡単 | 非対応 | まあまあよい |

# 検証
実際使ってみます。

## SourceGear DiffMerge
Mac OSやUbuntu等にも対応しています。
セットアップはホームページからダウンロードしてセットアップウィザードに従うだけなのでとても簡単です。

![DiffMerge.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442538/bbf5077b-f224-ecc1-ac2b-39367d5910a9.png)

UIは英語ですが、とてもシンプルなので問題には感じません。

機能としては

* 変更のある行ごとに「変更前のものを適用する」
* 「次の変更に飛ぶ」
* 「前の変更に飛ぶ」
* 「重要でない変更は隠す」（インデント等）

等があります。シンタックスハイライトはなさそうです。
シンプルさが好きでどのOSでも同じものが使いたいというのであればこれを使うのが良いように感じました。

## TkDiff
すみません、数時間粘りましたがUnityに認識させることができませんでした。

TkDiffはTcl/Tk環境が必要です。WindowsではTcl/Tk環境がないため、環境構築から始める必要があります。
>Tcl/Tk（ティクル・ティーケー）は、スクリプト言語 Tcl と、その GUIツールキット Tk を指す。（[Wikipedia](https://ja.wikipedia.org/wiki/Tcl/Tk)引用）

環境構築はActiveTclをダウンロードするか、SourceForgeからソースコードをダウンロードしてコンパイルするなどの方法があります。コンパイル方法については以下のQiitaの記事が参考になります。
[Visual Studio 2017でTcl/Tk 8.6.9をコンパイルする](https://qiita.com/tenomoto/items/4459bbd6bd86871acb8b)

次にTkDiffのダウンロード。
セットアップウィザードはありません。zipファイルをダウンロードして、展開して、ファイル名に拡張子を追加して（tkdiff → tkdiff.tcl）PATHを通したところまでやったのですが、Unityが上手く認識してくれずに断念しました。
Windows以外ならばうまく動くのかもしれません。

## TortoiseMerge
Windows専用。
TortoiseSVNという、バージョン管理システム（SVN)のクライアントアプリケーションに付随するソフトで、つまりTortoiseSVNをダウンロードする必要があるっぽいです。余分なものがついてくるので嫌な人は注意。また、日本語化するには追加で日本語化パックをインストールして設定をする必要があります。
これ単体ではググったとき日本語の情報が少ないです。

![tortoise.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442538/df444771-2541-7cd7-9002-c0aa36e578b2.png)

変更点、追加点が分かりやすく、機能も画像をパッと見て分かる通り豊富です。
UIは４つの中で最も優れているように感じました。簡単に使えます。

## WinMerge
Windows専用。日本語の情報が４つの中で最も多いように思えます。
セットアップも簡単です。

**※注意：WinMergeは64bit版だとUnity側で認識されなさそう**なので注意。Unityで利用する場合は32bit版をダウンロードするようにしてください。

![WinMerge.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442538/76130860-2d9c-adde-db1c-8e92357f69c0.png)

UIはTortoiseMergeには劣りますが（個人の感想です）使い辛いというほどではなく、機能も豊富です。

# 結論（個人の意見です）
どのOSでも同じものを使いたい or シンプルイズザベスト
→SourceGear DiffMerge

UI命 
 → TortoiseMerge

無難に、普通に、楽に使いたい or 日本語の情報が多いものがいい
→ WinMerge 32bit版