OmniAICreator/Qiita-1.07M huggingface dataset:
LINEのLIFFアプリについて少し調べた

# LINE公式アカウントとLINEミニアプリの違い
## 公式アカウント
- 企業向けアカウント。（個人でも作成できる）
- PUSH通知が送れる。
- 商品の宣伝に使える。

## ミニアプリ
- 店の予約や商品の購入（決済）ができる。
- LINEアプリがインストールされていれば使える。スマートフォン版LINEのみで動作。WEBブラウザからは使えない。
- 審査が必要。
- ユーザの行動データがとれる（離脱場所とか）。
- 公式ページ https://www.linebiz.com/jp/service/line-mini-app/

## LIFFアプリ
- LIFF(LINE Frontend Framework)と呼ばれる。
- ミニアプリとLIFFの違いは、https://lineapiusecase.com/ja/api/miniliff.html
- WEBブラウザからも使える（要ログイン）
- 審査は不要
- WEBサーバにデプロイしたら、すぐ確認できる
- LINEのユーザ認証を利用できる
- UIを直接ブラウザに送る必要がある。

# ミニアプリとLIFFアプリのどちらにするか？
- 審査がいらないので、LIFFアプリで先に作成。
- ミニアプリでしかできない事がやりたくなったら、ミニアプリを考える。


# ドキュメントおよびAPIリファレンス（LINE Developers）
【LIFF】
https://developers.line.biz/ja/docs/liff/
https://developers.line.biz/ja/reference/liff/

【LINEミニアプリ】
https://developers.line.biz/ja/docs/line-mini-app/
https://developers.line.biz/ja/reference/line-mini-app/

# 参考リンク
- [「LINEミニアプリ」は何を変えるのか？](https://marketing.itmedia.co.jp/mm/articles/2007/20/news124.html) ITmedia マーケティング 2020年07月20日 20時00分 公開
    - 2020年7月、LINEは「LINEミニアプリ」のエントリー受け付けを開始した。
Chatter グループの新規作成ボタンが機能しない


creating a new group in th Group Tab. I click on "New" but nothing happens

何故か分からないけどClassicにすれば可能みたい。


+ ["New" in Groups Tab](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A8zpWSAR)


+ [Error in "Update Photo" to complete the "Chatter for lighting experience" unit of the "Get stared with chatter" module](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Cv9WqSAJ)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/63743ff8-7062-a7e5-7d3d-bc0b46537620.png)
JavaScriptでvideoの再生、失敗を取得する方法

JavaScriptでvideoの再生、失敗を取得する方法になります。


## JavaScriptでvideoの再生、失敗を取得する方法

```html
<video id="video"></video>
```

```js
const video = document.getElementById('video')

// videoを再生
const startVideoPlay = video.play() 

if (startVideoPlay !== undefined) {
  startVideoPlay
    .then(() => {
      console.log('再生が成功')
    })
    .catch(() => {
      console.log('再生が失敗')
    })
    .finally(() => {
      console.log('再生の処理が終了')
    })
}
```
上記のように、Promiseでvideoの再生、失敗を取得することが可能です。
Vue.jsでCSVファイルをダウンロード (Shift-JIS)

## 概要
CSVファイルのダウンロードを実装したいときに、調べた内容をメモしておきます。
※ Windows環境で、操作するので「 Shift-JIS 」である必要がある
## サーバ側の実装 (PHP)
サーバサイドのAPIは、Laravelで実装する。

```
GET /csv/download
```
ルーティングを実装する。

```php:/routes/api.php
Route::namespace('Csv')
    ->prefix('/csv')
    ->group(function () {
        Route::get('/download', 'DownloadController')
            ->name('csv.download');
    });
```
コントローラーは、以下のように実装しています。
※「 `Maatwebsite\Excel` 」を使っています

```php:App/Http/Controllers/Csv/DownloadController.php
<?php
namespace App\Http\Controllers\Csv;

use App\Http\Controller;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Maatwebsite\Excel\Excel;
use App\Exports\Csv\SampleExport;

class DownloadController extends Controller
{
    public function __invoke(SampleExport $export): BinaryFileResponse
    {
        return $export->download('sample.csv', Excel::CSV, [
            'Content-Type' => 'text/csv'
        ]);
    }
}
```
エクスポート処理は、以下のように実装しました。

```php:App/Exports/SampleExport.php
<?php
namespace App\Exports\Csv;

use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithCustomCsvSettings;
use Maatwebsite\Excel\Concerns\WithHeadings;

class SampleExport implements WithHeadings, WithCustomCsvSettings
{
    use Exportable;

    /**
     * @return array
     */
    public function headings(): array
    {
        return [
            '商品ID',
            '商品コード',
            '商品名',
            '数量',
            '登録日時',
            '更新日時',
        ];
    }

    /**
     * @return array
     */
    public function getCsvSettings(): array
    {
        return [
            'use_bom' => true,
        ];
    }
}

```
## フロント側の実装 (Vue.js)
Vue.jsのコンポーネントに組み込みました。

```vuejs:/resources/js/components/Sample.vue
<template>
  <div>
      <button @click="download">ダウンロード</button>
  </div>
</template>

<script>
import axios from 'axios'
import { saveAs } from 'file-saver';
import Encoding from 'encoding-japanese';

export default {
  name: 'Sample',
  methods: {
    download () {
      axios.get('/csv/download')
        .then((res) => {
          // convert encoding. (utf-8 → shift-jis)
          const unicodeList = Encoding.stringToCode(res.data);
          const shiftJisCodeList = Encoding.convert(unicodeList, 'sjis', 'unicode');
          const shiftJisString = new Uint8Array(shiftJisCodeList);

          // save
          const fileName = 'サンプル.csv'
          let blob = new Blob([shiftJisString], {type: 'text/csv;charset=sjis'})
          saveAs(blob, fileName);
        }).catch(e => {
          this.$message.error(e.response.data.message)
        })
    }
  }
}
</script>
```
## まとめ
サーバ側で、Shift-JISエンコードのCSVファイルを出力しても、
ブラウザからダウンロードされるのは、UTF-8 (MacOS - Chrome)でした...

また、「 `Maatwebsite\Excel` 」でCSVをエクスポートするとUTF-8だったので、そのままだと文字化けしてしまいました。

結論としては、フロント側のJSで「 `Encoding` 」でShift-JISに変換しています。

## 参考サイト
* [Vue.js で SJIS コードの CSV をダウンロードさせる](https://www.moonmile.net/blog/archives/10404)
* [ブラウザのJavaScriptでShiftJISのcsvを作ってダウンロードさせる](https://qiita.com/fumihiko-hidaka/items/1fb8933072db76214079)
* [令和の時代に、JavaScriptで Shift-JISファイル作成 全 ... - web帳](https://www.webcyou.com/?p=10100)

以上
STAR-Fusionを非モデル生物で動かしてみる

#STAR-fusionいいよって聞いたから、動かそうと思った

融合遺伝子検出をしようと思って色々考えていたのだけど、やはりMappingに依存することがわかっているので、STARベースにしようと決めました。
そうそう、Mappingで非モデル生物においてpseudo Mappingはまともに機能していませんので、使っちゃだめですよ。
ちなみに決め手はこの論文。
https://genomebiology.biomedcentral.com/articles/10.1186/s13059-019-1842-9

元々出てきたときも凄い良いって話が多く、流石Broadだけあってパッケージの提供やアップデートが盛んで安心。
豚で実装したという報告も見たし、こりゃ楽勝だろうと思っていました。
<B>これが地獄の始まりだった</B>

##依存パッケージ多すぎ問題
詳しくはここにインストール方法が書かれている。
https://github.com/STAR-Fusion/STAR-Fusion/wiki/installing-star-fusion
STARとSamtoolsくらいならもう入れてあるし、まあこれくらいなら余裕かなーと思ってみると、エラー。
なんとSTAR-Fusionのバージョンによって使えるSTARのバージョンに違いがあるとのこと。
しかも細かい。
https://github.com/STAR-Fusion/STAR-Fusion/wiki/STAR-Fusion-release-and-CTAT-Genome-Lib-Compatibility-Matrix
しかも僕が犬で動作保証したバージョンは入っていないという悲惨さ。
うん、煩雑すぎるしバージョンを挙げるのが辛すぎるね。

##バージョンで泣かされるならSingularityを使えばよいじゃない
Singularityはコンテナイメージの一つで、言ってしまえばソフトが動いた環境を丸ごと持ってきてパッケージ化したようなもの。
（感覚で使っているから説明が正しいかわからない）
まあでも作者たちも推奨しているので、使わない手はないよね？
ということで遺伝研のBiotoolsの中を覗いてみると、あるある。
そして起動してみると、

```
 singularity exec -e star-fusion\:1.10.0--hdfd78af_1 /usr/local/lib/STAR-Fusion/ctat-genome-lib-builder/prep_genome_lib.pl --CPU 8 --genome_fa ~/share/CanFam3.1_transcript/Canis_familiaris.CanFam3.1.dna.toplevel.fa --gtf ~/share/CanFam3.1_transcript/Canis_familiaris.CanFam3.1.98.gtf --pfam_db ./Pfam-A.hmm.gz --dfam_db ./Dfam.hmm.gz

-found STAR at /usr/local/bin/STAR

-found makeblastdb at /usr/local/bin/makeblastdb

-found blastn at /usr/local/bin/blastn

- *** ERROR, cannot locate required tool in PATH setting: dfamscan.pl ***
- *** ERROR, cannot locate required tool in PATH setting: nhmmscan ***
- *** ERROR, cannot locate required tool in PATH setting: hmmscan ***
* Running CMD: cp /share/CanFam3.1_transcript/Canis_familiaris.CanFam3.1.dna.toplevel.fa /share/STAR_Fusion/ctat_genome_lib_build_dir/ref_genome.fa
```

どういうことだ、singularityのイメージなのにhmmerのソフトのPATHが無いだと？
DockerのMakeを読んでみると、全て`/usr/local/lib/`に置くようになっている。
なので`singularity shell -e`で確認してみると…ソフトが無い。
んなアホな。

##結局基本に忠実に行く羽目になる
まずBroadからSingularityのイメージを取得。
https://data.broadinstitute.org/Trinity/CTAT_SINGULARITY/
Dfam.hmm.gzではデータが多すぎて止まるので、人のデータのみのhmmファイルを取得して、実施。
https://www.dfam.org/releases/current/infrastructure/dfamscan/
そしてPfam.hmm.gzだと動かないので、事前に解凍してsingularity shellでhmmpressを実行。

```
gunzip -d Pfam.hmm.gz > Pfam.hmm
singularity shell -e star-fusion.v1.10.0.simg
hmmpress Pfam.hmm
exit
singularity exec -e star-fusion.v1.10.0.simg /usr/local/src/STAR-Fusion/ctat-genome-lib-builder/prep_genome_lib.pl --CPU 8 --genome_fa ~/share/CanFam3.1_transcript/Canis_familiaris.CanFam3.1.dna.toplevel.fa --gtf ~/share/CanFam3.1_transcript/Canis_familiaris.CanFam3.1.98.gtf --pfam_db ./Pfam-A.hmm --dfam_db human
```
余談だけど、dfamのデータベースは生物種（e.g. human, mouse）で指定できる。
これでようやくデータベースの作成が可能に。
んでどんな融合遺伝子が取れのかって？

<B>これからやるんだよ！</B>
【Android】Bitmapの色合い変更


`ColorMatrix`を使用することで色合いが変更できる。


```kotlin
fun Bitmap.filter(): Bitmap {
	//例としてグレースケール変更している
	val matrix = ColorMatrix(
		floatArrayOf(
			0.33f, 0.33f, 0.33f, 0f, 0f,
			0.33f, 0.33f, 0.33f, 0f, 0f,
			0.33f, 0.33f, 0.33f, 0f, 0f,
			0f, 0f, 0f, 1f, 0f
		)
	)
	val bitmap = Bitmap.createBitmap(width, height, config)
	val paint = Paint().apply { colorFilter = ColorMatrixColorFilter(matrix) }
	Canvas(bitmap).drawBitmap(this, 0f, 0f, paint)
	return bitmap
}
```

以前に書いた記事でも変更できるが、色合いを変更するだけならこちらの方が簡単。

https://qiita.com/nakashimaakio/items/fd58853efae507a40697


参考サイト

https://stackoverflow.com/questions/33474404/using-5x5-color-matrix-for-bitmap
[Rails] enumをハッシュ形式で設定する

#はじめに
enumに触れたので知識を深める。

#enumとは
ActiveRecordの提供するモジュールの1つ。値がデータベース内の整数にマップされる列挙型属性を宣言し、名前で照会できる。

#メリット/デメリット
###メリット
- データベースに保存されるデータサイズが小さく済むため、処理速度が速い。
- 定数名を変更したい時に改修が簡単

###デメリット
- データベース側では数値を保存しているため、何を表しているかが分からない。

#enumの設定方法
```
enum カラム名: { 定数1: 数値1, 定数2: 数値2, } 
```
この時、指定するカラムはintegerであることに注意する。

今回は「postsテーブル」にある「genreカラム」と「contentカラム」を例に取る。

```db/migrate/年月日時_create_posts.rb
    create_table :posts do |t|
      t.integer :genre
      t.text :content

      t.timestamps
    end
```

###カラムにenumを設定
今回は属性とデータベース整数の関係をハッシュで明示的にマッピングを行う。

```app/models/post.rb
class Post < ApplicationRecord
#省略

#ハッシュ形式でenumを設定
  enum genre: {
    others: 0,
    html: 1,
    css: 2,
    js: 3,
    ruby: 4,
    rails: 5
  }

end
```

配列を使用する場合、値からデータベース整数への暗黙的なマッピングは、値が配列に表示される順序から派生することに注意。

```ruby
class Post < ApplicationRecord
  # 配列で指定した場合
  enum genre: [ :others, :html, :css, ... ]
end
```

列挙型配列に値を追加したら、配列内のその位置を維持する必要があり、新しい値は配列の最後にのみ追加する必要がある。

未使用の値を削除するには明示的なハッシュ構文を使用する必要がある。



###確認
コンソールを起動して、出力結果を確かめる。

```console
# インスタンス生成から数値or定数名で指定
Post.create!(genre: 1, content: "これはHTMLです。")
Post.create!(genre: "html", content: "これはHTMLです。")
=> #<Post id: 1, genre: "html", content: "これはHTMLです。", created_at: "省略", updated_at: "省略">
=> #<Post id: 2, genre: "html", content: "これはHTMLです。", created_at: "省略", updated_at: "省略">

# 存在しない場合は ArgumentError
Post.create!(genre: "HTML", content: "存在しません")
=> #ArgumentError ('HTML' is not a valid genre)

# マッチする条件を数値or定数名で指定
Post.find_by(genre: 1)
post = Post.find_by(genre: "html")

post.genre
#=> "html"

post.genre_before_type_cast
#=> 1

post.html?
#=> true

post.css?
#=> false

Post.genres
#=> {"html"=>1, "css"=>2, "js"=>3, "ruby"=>4, "rails"=>5}

Post.genres[:css]
#=> 2
```

今回のenumをハッシュ形式で設定したものは、セレクトボックスと併用することで便利にプルダウンを実装する方法で学んだ。

参考もと
[Rails API/ActiveRecord :: Enum](https://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html)
[【Rails】Enumってどんな子？使えるの？
](https://qiita.com/ozackiee/items/17b91e26fad58e147f2e)
[Railsガイド/Active Record クエリインターフェイス](https://railsguides.jp/active_record_querying.html#enums)
[【Rails・ActiveRecord】_before_type_castを使って型が変換される前の値にバリデーションをかける](https://qiita.com/dnnnn_yu/items/4e1a0474ed047a9a92d2)
【React】Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:の対処法

<h2>症状</h2>
useHistoryを使用して、その動作確認で、ハンドラの動作させた際に下記エラーが発生してしまいました。

翻訳すると、
「キャッチされないエラー：無効なフック呼び出し。フックは、関数コンポーネントの本体の内部でのみ呼び出すことができます。これは、次のいずれかの理由で発生する可能性があります。」

1.2.3で記載されているいずれかの内容が原因でエラーが発生しているようです。

```react:エラー
react-dom.development.js:14906 Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
    at Object.throwInvalidHookError (react-dom.development.js:14906)
    at useContext (react.development.js:1504)
    at useHistory (hooks.js:18)
    at SubmitHandle (fuga.jsx:40)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4070)
    at executeDispatch (react-dom.development.js:8243)
    at processDispatchQueueItemsInOrder (react-dom.development.js:8275)
    at processDispatchQueue (react-dom.development.js:8288)
    at dispatchEventsForPlugins (react-dom.development.js:8299)
    at react-dom.development.js:8508
    at batchedEventUpdates$1 (react-dom.development.js:22396)
    at batchedEventUpdates (react-dom.development.js:3745)
    at dispatchEventForPluginEventSystem (react-dom.development.js:8507)
    at attemptToDispatchEvent (react-dom.development.js:6005)
    at dispatchEvent (react-dom.development.js:5924)
    at unstable_runWithPriority (scheduler.development.js:468)
    at runWithPriority$1 (react-dom.development.js:11276)
    at discreteUpdates$1 (react-dom.development.js:22413)
    at discreteUpdates (react-dom.development.js:3756)
    at dispatchDiscreteEvent (react-dom.development.js:5889)
```

下記がソースになります。

```react:fugaCreate.js
import React from "react";
import {useHistory} from "react-router-dom"

export const FugaCreate = () => {

    function SubmitHandle() {
        const history = useHistory()
        history .push("/hoge")
    }
    return(
      <button onClick={SubmitHandle}>ボタン</button>
    )
}
```


<h2>解決策</h2>
useHistoryの宣言をトップレベルに移動させることで、解決しました。

Reactのhookを使うとき、トップレベルにhookの宣言をしていないと、トップレベルで宣言したhookの数と、動作させたときのhookが異なっているため、上記エラーが発生してしまうようです。

```react:fugaCreate.js
export const FugaCreate = () => {
    const history = useHistory()

    function SubmitHandle() {
        history .push("/hoge")
    }
    return(
      <button onClick={SubmitHandle}>ボタン</button>
    )
}
```

<h2>参考</h2>
https://qiita.com/tatsumin0206/items/4e1076e2deedf20a9485
importとrequireの違い。【importの際の中括弧についても】

laravelとvue.jsでアプリを開発していて、基礎的な`import`と`require`の違いについて気になったので、調べてみました。

この記事はその時のメモです。

## 前提：モジュールの読み込み方法はいくつかある。

「[こちら](https://qiita.com/minato-naka/items/39ecc285d1e37226a283)」 の記事によれば下記の通り。

>モジュールを読み込むための方法、仕様は
何種類かあり、
それぞれ書き方が違い、動く環境も違います。

>そのモジュール読み込みの仕様の主要なものとして、
ESM (ECMAScript Modules)と
CJS (CommonJS Modules)があります。
※ほかにもいくつかあるが、主要なのはこの２つ

>今回のテーマであるimportを使うのがESM方式で、
requireを使うのがCJS方式となります。

重要なのは、
**・importを使うのがESM方式
・requireを使うのがCJS方式**
って部分かな。

**ちなみに、import(ESM)は非同期ロード、require(CJS)は同期ロードらしいです。**

## import

importは、主に下記の2つの書き方がある。

```js
import nokakko from "./hoge.js";

import {yeskakko} from "./hoge.js";

```

この中括弧があるかどうかの違いは、

```js:hoge.js
export default 'クラスとか変数とか';
export const yeskakko = '同じくクラスとか変数とか';
```

上記の解説が下記の通り。

>export defaultで公開した値は
中括弧なしでimportできる
どんな名前でimportしてもよい
exportで公開した値は
中括弧をつけてimportする
export時の変数名でimportする
{ xxx as yyy }とすることで任意の変数名に変えることができる


[ES2015のモジュール機能(import/export)](https://qiita.com/ozaki25/items/9723cb3c1c72845157d5)に載ってました。

### default

厳密ではない解説とのことですが、下記がわかりやすかったです。

>「default でエクスポートした関数は自動で「default」という名前が付けられ、しかも import 時にその名前を省略できます。」

[Vue の export default と import](https://www.shookuro.com/entry/2018/09/22/172636) からの抜粋です。

**ちなみにdefaultは1つのファイルで1回しか使うことができません。（defaultの名前が重複しちゃいますからね。）**

## require

`require構文`でモジュールを読み込む際は下記のようにする。

``` js:module.js(モジュール側)
module.exports = function() {
    console.log('Hello World!!');
}
```

```js:app.js(読み込み側)
const helloWorldModule = require('./module.js');

helloWorldModule();
// 出力：Hello World!!
```

[jsのimportとrequireの違い](https://qiita.com/minato-naka/items/39ecc285d1e37226a283)から抜粋です。

これでかなりモヤモヤが解消された。

おしまい。
Electron+Vueで「Uncaught ReferenceError: __dirname is not defined」エラー

ダイアログを表示しようとすると、以下のエラーが発生しました。

```bash
Uncaught ReferenceError: __dirname is not defined
    at eval (webpack-internal:///./node_modules/electron/index.js:4)
    at Object../node_modules/electron/index.js (chunk-vendors.js:4725)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js&:4)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/App.vue?vue&type=script&lang=js& (app.js:938)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (webpack-internal:///./src/App.vue?vue&type=script&lang=js&:2)
```

## 対処法
プロジェクトのルートに「**[^1]vue.config.js**」を作成すると解決しました。

```vue.config.js
module.exports = {
  pluginOptions: {
    electronBuilder: {
      nodeIntegration: true,
    },
  },
};
```

## レンダラープロセス側の実装

```App.vue
<template>
  ...
  <v-button @click="showDialog" />
  ...
</template>

<script>
import { ipcRenderer } from "electron";

export default {
  name: "App",
  ...
  methods: {
    showDialog: function() {
      ipcRenderer.invoke("showDialog", null);
    },
  },
}
</script>
```

## メインプロセス側の実装

```background.js
// ipcMain, dialogを追加
import { app, protocol, BrowserWindow, ipcMain, dialog } from "electron";

ipcMain.handle("showDialog", async (event, data) => {
  dialog.showMessageBox({
    title: "タイトル",
    message: "詳細",
  });
});
...
```

## 参考
[How fix __dirname not defined when using electron events with Vue?](https://stackoverflow.com/questions/62777834/how-fix-dirname-not-defined-when-using-electron-events-with-vue)

[^1]: アプリ全体に関わる設定を書くためのファイル
Salesforce_JavaScript開発者I

<P><B>勉強と準備</B></p>

Salesforce JavaScript Developer I （CRT600 ）の認定<B>準備</B>

<B>概要概要</B>
Salesforce認定JavaScript開発者Iになることで、キャリアの次のステップに進む準備はできていますか？このコースでは、試験の構造と目的に関する詳細を説明することで、問題解決スキルを磨き、JavaScriptプログラミング言語の主要な機能と概念に関する知識を強化するのに役立ちます。

<B>このコースができる人</B>
・Webスタック用のフロントエンドおよび/またはバックエンドJavaScriptアプリケーションの開発に関する知識、スキル、および経験を持っている個人。

・オブジェクト指向プログラミング言語を使用したアプリケーションの設計、開発、テスト、およびデプロイの経験があり、それらのスキルをJavaScriptを使用したアプリケーションの構築に移行したいと考えている開発者。

<B>内容</B>
JavaScriptプログラミング言語の主要な概念（型変換、高階関数、非同期プログラミング、オブジェクト継承、プロトタイプ）を効果的に使用します。
JavaScriptコードのエラーをテスト、デバッグ、および処理する方法を説明します。

　レッスンとトピック
　　JavaScriptの基本

　データ型と変数
　　型変換（明示的および暗黙的）

　コレクション
　　文字列、数値、および日付の操作
　　JSONの操作


　オブジェクト、関数、およびクラス
　　オブジェクトの作成

　関数の定義
　　オブジェクトのプロトタイプ
　　クラスの宣言
　　JavaScriptモジュールの使用


　ブラウザとイベント
　　ドキュメントオブジェクトモデル
　　DOMイベント
　　ブラウザ開発ツール


　デバッグとエラー処理
　　エラーのスローとキャッチ
　　コンソールの操作


　非同期プログラミング
　　コールバック関数
　　約束
　　非同期/待機


　サーバーサイドJavaScript
　　Node.js CLI
　　Node.jsライブラリ
　　Node.jsでのデバッグ
　　npm


　テスト
　　アサーション
　　テストの種類

<B>お勧め</B>
あなただけのために設計された学習パスであなた自身のペースで学びましょう。
・<a href="https://trailhead.salesforce.com/en/users/strailhead/trailmixes/prepare-for-your-salesforce-javascript-developer-i-credential">SalesforceJavaScript開発者Iクレデンシャルの準備</a>
・<a href="https://trailhead.salesforce.com/ja/content/learn/trails/study-for-the-salesforce-javascript-developer-i-exam">JavaScript開発者I試験のための研究</a>
ActiveRecordのattributes系メソッドは自動で型変換が行われる

初めて知ったことだったので、知見として残しておきます

データ更新時にuserにデータを格納して、それを使って処理を行う必要があるとします

```ruby:hoge_controller.rb
class HogeController < ApplicationController

  ~(中略)~

  def update
    user = assign_attributes(user_params) # user_paramsは strong_parametersです
    hoge = Hoge(user, current_user)
    if user.valid? && user.save
      p "更新成功！"
    else
      p "更新失敗！"
    end
  end
end
```

```ruby:user.rb
class User < ApplicationRecord
  # name String
  # age  Integer
  # ageが正規表現で文字列等を弾いてないことが重要
  with_options presence: true do
    validates :name
    validates :age
  end
end
```

このとき、Userの入力フォームで`age`に対して文字列を入力した場合、`更新成功！`が出力されて`age: 0`の状態で登録されます
これは単一指定のattributeでも同様の現象が発生します

理由はattributesやassign_attributesを使ってカラムにデータを登録した際、元となるattribute内で`write_attribute`によるキャストが行われるから、ということでした
[attributesは内部的にはassign_attributesと同一ですので結果は同じになります](https://github.com/rails/rails/blob/75ac626c4e21129d8296d4206a1960563cc3d4aa/activemodel/lib/active_model/attribute_assignment.rb)

[こちらのQiita記事により詳しい解説が載っておりました](https://qiita.com/tyamagu2/items/8abd93bb7ab0424cf084)

# まとめ
**数値型のカラムに対してはちゃんとformatの記載をしよう！**
AWS EC2のsshがすぐ切れてしまう件について

AWSのEC2をターミナルで起動している際、sshがすぐ切断されて
client_loop: send disconnect: Broken pipe
と表示されてしまうことが多くあります。
私もこれに悩まされてどうにかならないか調べてみたところ、解決方法があったので記載します。

#### 動作環境
Mac OS ターミナル

1.EC2のsshd_configを修正する

```sample1
sudo vi /etc/ssh/sshd_config
```
すると、viが開くので、

```sample2
ClientAliveInterval 0
ClientAliveCountMax 3
```
という項目を探します。
ClientAliveIntervalは、クライアントのチェックを行う頻度
ClientAliveCountMaxは、クライアントがチェックをカウントする最大回数
を表すので、ここを修正します。


```sample3
ClientAliveInterval 60
ClientAliveCountMax 120
```

こうすることで、60秒ごとにチェックをし、120回までは接続が解除されなくなります。
つまり2時間接続が保たれます。
RaspberryPi pico 複数の入力割り込み

#はじめに
前回TimerによるLチカを行いました。
ただ、ボタンの入力はポーリングで判断しておりましたが、割り込みで可能になりました。

#マニュアルを良く読む
gpio_set_irq_enabled_with_callback()関数をよく読むと、
Currently the GPIO parameter is ignored, and this callback will be called for any enabled GPIO IRQ on any pin. 
Googleで翻訳すると、
現在、GPIOパラメーターは無視され、このコールバックは、任意のピンで有効になっているGPIOIRQに対して呼び出されます。
と記載されています。
「GPIOパラメータは無視され」と書いてあります。

#以前思うように動作しなかたロジック
```c
gpio_set_irq_enabled_with_callback(15, 0x4u, false, callback_buttonL);
gpio_set_irq_enabled_with_callback(16, 0x4u, false, callback_buttonR);
gpio_set_irq_enabled(15, 0x4u, true);
gpio_set_irq_enabled(16, 0x4u, true);
```

上記を実行すると、GP15のボタンを押しても、callback_buttonR関数が呼ばれてしまいました。

#意図した動作となったロジック
```c
gpio_set_irq_enabled_with_callback(15, 0x4u, false, callback_button);
gpio_set_irq_enabled(15, 0x4u, true);
gpio_set_irq_enabled(16, 0x4u, true);
```

callbackの関数は1つにして、GP15とGP16と指定しました。

callback_button関数は、下記のようにしました。

```c
void callback_button(uint gpio, uint32_t events)
{
	if(gpio == 15 && events == 4u){
		' GP15の処理を記載
	}
	if(gpio == 16 && events == 4u){
		' GP16の処理を記載
	}
}
```

#まとめ
マニュアルは良く読むようにします。
raspiにスマートリモコン&メディアプレイヤーをのせてみた①

raspi上で動くスマートリモコン&メディアプレーヤを作成しました。
セットアップ手順も作成しています。   

初心者向けに作成しているつもりなので興味があればレッツトライ！ 
ちょっとだけ初期費用はかかりますけど今時の中学生のおこづかいで買えるかもしれません。
※お父さんのおこづかいで買えるかはわかりません！！

# 全体図
![whole.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282746/0fb54f72-9e55-6ad6-4c05-4ea7776159b0.png)

# 画面見本
### 寝室のエアコンとライト   
ステータスはデバイスサーバに保存しブラウザ側に同期
![bed_ambient1 (コピー 1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282746/26233916-06ad-1c80-407d-95b3e5c07f8b.png)

### 寝室のプロジェクタ   
こどものねかしつけに便利な<a href="https://www.segatoys.co.jp/toy/9172/">プロジェクタ</a>  ステータスは持たない
![bed_projector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282746/6aeaa83f-11d3-66be-4a1e-654b917fa9fc.png)

### リビングのエアコンとライトとモニター   
寝室のエアコン/ライトとステータス管理は別   
![living_ambient (コピー 1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282746/e4a38ac4-dc01-25b4-c3ea-beb0fb05bf68.png)

### リビングのメディアプレーヤ  
- 再生/一時停止/停止/バックスキップ/フォワードスキップが可能  
- 再生位置の同期機能
- ファイルアップロード（同一ファイル名はアップロード不可）
- ビデオのタップでスマホ上で再生
- ビデオのロングタップで再生対象か対象外かを切り替え

![living_media.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282746/259edfbf-5a50-4664-1010-f93d2440c8a9.png)

# 機能概要
- raspi4
    - ウェブサーバ・・・スマホと各種機能の仲介処理
    - メディアサーバ・・モニターにビデオを出力。再生状況をウェブサーバ経由でスマホ側に送信。
    - ファイルサーバ・・ファイルを保存。ファイル一覧をウェブサーバ経由でスマホ側に送信。
    - デバイスサーバ・・IR情報を各部屋にあるIR送信サーバに転送。家電情報をウェブサーバ経由でスマホ側に送信。

- raspiZero
    - リビングと寝室に設置。デバイスサーバから送信されたIR情報を赤外線にして家電を操作。


# 実装概要
 - raspi4
    - ウェブサーバ・・・go(echo&webSocket), grpc※
    - メディアサーバ・・vlc(libvlc-go), grpc※
    - ファイルサーバ・・ファイル情報をjson保存, grpc※
    - デバイスサーバ・・IR送信サーバへhttp:getリクエストで送信, grpc※   
    ※サーバ間通信

- raspiZero
    - getリクエストで受け取った情報を赤外線に変換して送信   


# リンク
## ソースコード
<a href="https://github.com/YujiYabe/goMediaServerDemo">こちら参照</a>
※リンク切れてました。。

# リンク
## セットアップ
<a href="https://qiita.com/yujiyabe/items/20c567ea4362a44bf942">こちら参照</a>

## 共通設計
<a href="https://qiita.com/yujiyabe/items/1eb8038031129e270243">こちら参照</a>

## サーバ
以下参照
<a href="https://qiita.com/yujiyabe/items/34e64b9f46e06e325c8f">ウェブサーバ</a>
<a href="https://qiita.com/yujiyabe/items/94cfd174a84fdad1d9fc">ファイルサーバ</a>
<a href="https://qiita.com/yujiyabe/items/6955b61d4cf47cb653a0">メディアサーバ</a>
<a href="https://qiita.com/yujiyabe/items/2ebf563c9ca8cd7599fd">デバイスサーバ</a>

## ブラウザ
<a href="https://qiita.com/yujiyabe/items/743d286ee4b4657b069c">こちら参照</a>

## 引用元
参考にした記事はたくさんあるのですが、メモってなかったので時間のあるときに追加します。
node.jsを学習中に出てきた用語などをまとめてみた。

まじで基礎的なこともメモる。

（あとメモが10件に達したので公開します😞）

##Node.js（Js系）の用語

###オブジェクト

他の言語でいう連想配列みたいなもので、Javascript（Node.js）では,大体がオブジェクト。

「キーと値がセットになったもの」がたくさん入っているのがオブジェクトみたいな感んじ。

###プロパティ

キーと値がセットになっているもの。

###コールバック関数

関数に渡す関数のこと。

## npm関連

### npm -i

`npm install`と同じ。ただのエイリアス。

### package-lock.json.

実際にインストールされたパッケージとバージョンを管理している。

これがあることで、開発者同士でバージョンが異なることがない。

例えば、`package.json`に`"パッケージ": "^1.3.0"`みたいに記述されていれば`^`があることにより、`npm install`を実行した時点での最新バージョンがインストールされて、開発者同士で使っているバージョンが異なることがある。

それは困るので、`npm v5以降`は`package-lock.json`が導入された。

`npm install`は`package-lock.json`をもとにパッケージをインストールし、`package.json`に指定されたバージョンと矛盾していれば、`package.json`が優先される。

##IT用語全般

###API

apiは「決められたHTTPリクエストを送信すれば、決まった値を返してくれるもの」みたいな感じ。

###ミドルウェア

リクエスト・レスポンスサイクルにおいて、任意の処理を行う関数のこと。

例：「あるURLにアクセス（リクエスト）したら、ログイン済みユーザーが確認する。」
VIVE Pro EyeでSRWorksを使う

VIVE Pro Eyeのフロントカメラを使ってMRコンテンツを作成するために開発されたSRWorksというパッケージがあります。
バージョンの問題やUnityのXR用の環境設定などで導入につまずいたので忘備録として残しておきます。

###環境概要
- Unity 2019.3.2f1
- Unity SteamVR Plugin 2.7.3 (sdk 1.14.15)
- SRWorks_v0.9.7.1_Unity_Plugin

###導入順序

##### 1. 必要ファイルのDL 

先に以下のサイトからファイルをDLしておく

[Vive SRWorks SDK Release 0.9.7.1](https://developer.vive.com/resources/vive-sense/sdk/vive-srworks-sdk/0971/)
必要なファイルは以下の3つ

- SRWorks (XR) SDK Unity Plugin
- SRWorks (XR) SDK Unity Samples
- SRWorks Runtime

##### 2. SRWorks Runtimeをインストール

- ダウンロードしたzipファイルを解凍し、DLしたVIVE_SRWorksInstaller_0.9.7.1.msiを開き指示に従う

##### 3. VIVE Pro Eyeは起動しておき、SteamVRのホーム画面が見える状態にしておく
<font color="red">※ このとき、SteamVRソフトからVIVE Pro Eyeのフロントカメラへのアクセスを有効にしておく必要あり</font>

https://www.vive.com/jp/support/vive/category_howto/activating-the-front-facing-camera.html

##### 4. Projectを新規作成する

3Dを選択、名前は任意

##### 5. XR機能の設定

- まずはFile/Build Settingウィンドウの中のPlayer Settingを開く
- XR Plug-in Managementをインストールし、Initialize XR on Startupの項目にチェックが入っていることを確認する
- Player Settingウィンドウを閉じたあと、AssetsにXRというファイルが追加されていることを確認する

<font color="red">※ このとき、先にSRWorks SDK Unity PluginをインストールしてしまうとXR Plug-in Managementをインストールできなくなったので注意</font>

##### 6. SteamVR Pluginを導入する

- Asset StoreよりSteamVR PluginをDL&Importする
- インストール中いくつかのウィンドウが出てくるのでAccept Allを繰り返しクリックする
- インストール完了後、Windows/SteamVR Inputウィンドウを開き、Save and generateボタンをクリックする
- Assets/SteamVR_Inputが生成されていることを確認したあと、Open binding UIからバインディング設定ウィンドウを開く
- Current Binding/Editからコントローラーバインディング設定ウィンドウを開きReplace Default Bindingをクリックする

<font color="red">※ SteamVRソフトの言語設定が英語になっていないとReplace Default Bindingボタンが表示されなかったので注意</font>

##### 7. SRWorks-Pluginを導入する

- 先程DL&解凍しておいたファイルの中にあるVive-SRWorks-Unity-Plugin.unitypackageとVive-SRWorks-Unity-Experience.unitypackageをUnityへimportする
- Assets/Vive_SRExperience/Scenes/Demoを実行すると様々なデモを体験することができる

#### 参考記事

##### 公式ページ
- [VIVE SRWorks SDKコミュニティフォーラム（英語）](https://forum.vive.com/forum/69-vive-srworks-sdk/)
- [VIVE SRWorks SDKガイド（0.9.3.0用）](https://hub.vive.com/storage/srworks/)

##### 個人記事
- [UnityでVIVE cosmosを扱う【SteamVR Plugin導入】](https://qiita.com/T170521/items/7098a13d6332128b630f)
- [SteamVR Unity Plugin v2.2.0でのインプット
]
(https://qiita.com/sakano/items/d87a9b11c23a9bbe166f#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B7%E3%83%BC%E3%83%B3%E3%82%92%E5%8B%95%E3%81%8B%E3%81%99%E6%89%8B%E9%A0%86)
dockerコンテナアクセス時のエラー：OCI runtime exec failed: exec failed: container_linux.go:000: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown への対処法

コンテナに入るコマンドを以下に変更
docker exec -it コンテナID /bin/sh  

以下の記事を参考にさせていただきました、ありがとうございます。
https://gamushiros.hatenablog.com/entry/2018/07/13/133313
ESP-WROOM-02搭載移動ロボットをMQTTで制御する - ハード編

本記事の内容はQiitaの[コミュニティガイドライン](https://blog.qiita.com/notice-community-guideline-update/)に沿わないと判断したため、Zennへ移行しました。

https://zenn.dev/yakiimo121/articles/d24c15bf513732
VB6.0から.NETへマイグレーションについて

VB6.0から.NETへマイグレーションについて
１．VB6.0から.NETへマイグレーション理由
２．VBマイグレーション手順
３．マイグレーション重要なポイント
４．まとめ

## １．[VB6.0から.NETへマイグレーション理由](https://onetech.jp/blog/why-need-to-migrate-from-vb6-to-vb-net-8665)
主な理由
•WindowsXPのOSサポートが終了したため、継続使用にはセキュリティーリスクが伴うようになります。
•VB6.0での開発支援ツールとしてサポート停止
•VB6.0の技術者が減少し、保守要員の確保が難しい
•Windows７移行での動作保証がございません

## ２．[VBマイグレーション](https://onetech.jp/service/vb-migration)手順
VB6.0から.NETへ単純にアップグレードだけではなくて、手順に沿って実施する必要があります。下記の手順を紹介したいと思います。
①資産可視化：変換対象なプログラムを明確する
②調査や分析：Microsoftツールで変換を実施する。この段階でコンパイルエラーやランタイムエラーは二つ種類があります。
　　　変換バージョンより２段階変換する必要があります。

③変換設計 ：コンパイルエラーやランタイムエラーのエラーに対して
a.エラーパータンを定義する
b.各パータンに対して処置方法も決定する
c.ツール自動変換するか手動変換するかの切り分けを実施する。
d.上記のパータンを基づいて、変換ツールを作成する

④サンプル変換
a.マイグレーション対象範囲内から特性機能なプログラムを変換、テストを実施
b.変換ツールを検証し、追加対応などが必要に応じてツールを修正する。

⑤変換修正
a.検証した変換ツールにてすべてソースの変換を実施する
b.手作業の対象プログラムを修正する

⑥比較検証
  現行システムとマイグレーション後の処理結果を比較する
⑦受入テスト
a.顧客検証を実施
b.不具合などが発生すれば修正
![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/69393ef4-070f-2192-475e-129d06ded840.jpeg)

## ３．マイグレーション重要なポイント
### ３．１二段階変換
上記の手順で調査分析と変換設計です。Vb6.0からVS2017へ変換する際に2段階を実施する必要があります。
①VB6.0 → VS2008へアップグレード
②VS2008 → VS2017/VS2019へアップグレード
下記のイメージでご参照ください。
![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/5b2e638d-2f2d-6d10-d3b2-914141b9c2a4.jpeg)
 

### ３．２ActiveReport帳票
　　　ActiveReportのバージョン1.5Jから14Jへ変換することも出来ないので、下記の順番を実施しないといけない。
・ActiveReportバージョン1.5J　→　バージョン2.0J
・ActiveReportバージョン2.0J　→　バージョン14J
　　
### ３．３エラー一覧でパータン定義
**コンパイルエラー**
アップグレード後でコンパイルする際にエラーが発生する。その際にエラーは一覧を抽出して各エラーに対して対応方法を定義する
 ![3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/45f69dc9-0a58-bf0a-63ed-e87eae855628.jpeg)

対応方法を明確する。
![4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/2919da32-879e-7d85-01d3-9202e047cfef.jpeg)

 
**実行エラー：**
ビルド後アプリケーションを実行する際に発生したエラーを一覧にして各エラーの対応方法を明確する
　
 ![5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/78da9989-d1e3-9cdb-96e2-7adfa18ebf3a.jpeg)

## ４．まとめ
　　VB6.0から.NETへ変換する際に円滑に進めるため変換手順に沿って実施するとスムーズにマイグレーションを実施する可能です。

Source: [VB6.0ユーザー必見！VB.NETへの移行ガイドライン](https://onetech.jp/blog/why-need-to-migrate-from-vb6-to-vb-net-8665)
PhotonServerのアプリケーションをEC2にデプロイする手順

**自分用メモなので悪しからず**

1. EC2インスタンスを起動してログイン
1. PhotonServerとライセンスファイルをダウンロードして展開
1. .NET Coreをインストール
1. PhotonServerで作ったアプリケーションのソースコードをチェックアウトしてdotnet build
1. ビルドしたバイナリをdeploy/[プロジェクト名]に放り込む
1. 設定ファイルにアプリケーションの設定を追記
1. **ファイアウォールの設定で、アプリケーションの使用するポートを開ける**←VPCのSecurityGroupとは別なので要注意
1. PhotonControlを起動してサーバアプリケーションを開始
2021年版 ユニバーサルリンクが更新されなくてハマった話

# 結論
- ビルド番号が違うアプリをインストール
- Storeから入っていたアプリをTestFlightからインストール

の２種類の方法で治りました。
どこかの記事で、アプリ再インストール時に **apple-app-site-association** を見に行っているという話がありましたが、単純に再インストールしただけでは反映されませんでした。

検索で上に出てくる記事が総じて少し古いのでそのときから仕様が変わってるっぽいですね :thinking:

なおこちらは **iOS 14.5.1** で検証しました
【linux】useradd でホームディレクトリは作るけど skel はコピーしない

useradd で新規ユーザ追加とともにホームディレクトリも作成するため -m オプションを使用すると、そのままでは /etc/skel がコピーされます。
これを抑制するには、
-m -k /dev/null
とすれば良いみたいです。
centOS7 で確認しました。
ATTダイアログ前の説明画面でアクセプト→リジェクト→アクセプトされたので記録

##はじめに
トラッキング許可のダイアログを出す手前で、事前説明を行っていたのですが、一度アクセプトされた内容を、別件で再申請した際にリジェクトされたので、これから申請される方の参考になるよう記録します。


##2021/04/04 下記画面でアクセプト

<img width="340" alt="IMG_5808.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165708/36453185-7e0d-8eba-71b9-2f9685de682d.jpeg"> <img width="340" alt="IMG_5809.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165708/cfa4e7b1-323c-f98b-c186-7479f8450112.jpeg">

##2021/05/05 別件でアップデートを申請したところ上記画面を理由にリジェクト

##2021/05/06 下記画面で再申請したところアクセプト

<img width="340" alt="IMG_5789.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165708/3f586fd0-2a67-6163-2e39-13c2c415bab1.png"> <img width="340" alt="IMG_5793.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165708/ac822f58-67c0-90c2-fbf3-a36b361eb5ae.png">

##参考）2021/05/13 別アプリにて、下記画面で初申請したところアクセプト

<img width="340" alt="IMG_5893.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165708/dc809f1d-bd7e-c2d1-ef77-02815f4a98fd.png"> <img width="340" alt="IMG_5894.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165708/0b080507-07fa-94ad-fb4b-373dd2432eff.png">
SwiftUI トラッキング許可のポップアップ(ATTダイアログ)表示とAdmob SDKの初期化

## 1. Info.plistへ、ポップアップに表示させる文面を追加

```
<key>NSUserTrackingUsageDescription</key>
	<string>
広告を最適化するために使用します。
なお、本アプリが個人情報にアクセスすることはありません。</string>
```

## 2. 説明ページを実装（任意） & ポップアップを表示、Admob SDK初期化
追記　アプリがアクティブになってからでないとポップアップが表示されなくなりました。（いきなりinitやonAppearで表示するなどが不可になった。）

【例文】
"本アプリでは、広告を表示しています。\n次の画面で「許可」を選択すると、あなたに合った広告が表示されやすくなります。\n(許可しなくても、アプリのすべての機能を利用できます)"


```
//サンプルコード
struct TrackingExplanationView: View {
    @Binding var shouldShowTrackingExplanationView: Bool
    
    var body: some View {
        VStack {  
            Text("テキスト")

            Button(action: {
                ATTrackingManager.requestTrackingAuthorization() {_ in
                    GADMobileAds.sharedInstance().start(completionHandler: nil)
                }
                shouldShowTrackingExplanationView = false
                UserDefaults.standard.set(false, forKey: "shouldShowTrackingExplanationView")
            }) {
                Text("ボタン")
            }
        }
    }
}
```
```
//サンプルコード2
init() {
    ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
        GADMobileAds.sharedInstance().start(completionHandler: nil)
    })
}
```
Ubuntu18.04をZabbix5.4にアップグレードするとDatabase errorで失敗する

久しぶりにZabbixのバージョンアップ時にエラーが出て焦りました。気軽にバージョンを上げて解決に悩んで2時間程消耗したので、誰かの助けになれば幸いです。

##環境
- Ubuntu 18.04.5 LTS
- Zabbix 5.2 -> 5.4

## 現象

[公式のアップグレード手順](https://www.zabbix.com/documentation/current/manual/installation/upgrade/packages/debian_ubuntu)通りに行ったのだが、Database errorが表示され正常にアップグレードできない。

![スクリーンショット 2021-05-20 10.21.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14768/01b382c8-3e22-237b-b970-9c65b182b6f6.png)

## 確認

```[Z3005] query failed: [1832] Cannot change column 'scriptid'```という感じでQueryが通らずアップグレードが失敗している。

```:/var/log/zabbix/zabbix_server.log

 1756:20210520:101837.080 database upgrade failed
  1759:20210520:101847.314 Starting Zabbix Server. Zabbix 5.4.0 (revision 5059e20a75).
...
  1759:20210520:101847.315 using configuration file: /etc/zabbix/zabbix_server.conf
  1759:20210520:101847.325 Unsupported DB! MariaDB version is 50505 which is smaller than minimum of 100037
  1759:20210520:101847.326 current database version (mandatory/optional): 05030069/05030069
  1759:20210520:101847.326 required mandatory version: 05040000
  1759:20210520:101847.326 starting automatic database upgrade
  1759:20210520:101847.327 [Z3005] query failed: [1832] Cannot change column 'scriptid': used in a foreign key constraint 'c_opcommand_2' [alter table opcommand modify `scriptid` bigint unsigned not null]
  1759:20210520:101847.327 database upgrade failed
```

## 解決方法

Query失敗で不正データがあるのかと思って1時間程悩み戻しも検討するが、Databaseのバージョンの問題との事

https://www.zabbix.com/forum/zabbix-troubleshooting-and-problems/424860-ubuntu-18-04-zabbix-5-0-5-to-5-4-upgrade-database-failed-error
 
```  1759:20210520:101847.325 Unsupported DB! MariaDB version is 50505 which is smaller than minimum of 100037```

たしかに...。普通にupgradeしても自動ではMariaDBのバージョンはそれ以上上がらないようなので、という事でサービスを停止後に10.5を明示してインストールを実行

```
# sudo service zabbix-server stop
# sudo apt-get install mariadb-server-10.5
# sudo service zabbix-server start
```

## それでも動かない場合 (Row size too large)

さらに、```Row size too large```が出たので設定変更を行います。
（※すでに前バージョンで設定済で上書きしなければ問題無い可能性有り）

```:/var/log/zabbix/zabbix_server.log
....

  3446:20210520:102323.335 [Z3005] query failed: [1118] Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs [alter table `config` add `url` varchar(255) default '' not null]
```

my.cnfやmariadb.cnfに```innodb_strict_mode=0```を追加します。

```:/etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
innodb_strict_mode=0
```

参考:

https://qiita.com/masahiro_0316/items/8e6c6371b5d40b288a26
【Nuxt.js】v-htmlでdirective can lead to XSS attack.とwarningが出る対処法

先日NuxtのvueファイルのtemplateをpugからHTMLに下記の備忘録のように書き換えたのですが
HTMLのv-htmlの部分が黄色いwarnの嵐だったので対処法をまとめました。 

https://qiita.com/hiroyukiwk/items/637639a20127c1783596


こんなかんじでv-htmlの部分がwarnになります。
![スクリーンショット 0003-05-20 10.33.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/956d024f-7efe-cae9-392d-128345b159e5.png)


```vue
<template>
  <v-main>
    <h1 v-html="title" />
  </v-main>
</template>

<script>
export default {
  data () {
    return {
      title: '<span>タイトル<br>下見出し</span>'
    }
  }
}
</script>
```

```
 WARN  ESLintError                                                                                                                                                          friendly-errors 09:53:46

                                                                                                                                                                            friendly-errors 09:53:46
/hogehoge/pages/index.vue
  3:9  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

✖ 1 problem (0 errors, 1 warning)
```

## 簡単な対処法
v-html属性に変数をバインドするとプレーンなテキストではなくHTMLを表示させてくれます。
ESLintを設定している場合warnが出力されてしまいます。

```
warning  'v-html' directive can lead to XSS attack  vue/no-v-html
```

ここに書かれていますが、ユーザーからの投稿内容などが入り得る場合などはXSSの危険があるため非推奨とされています。

https://jp.vuejs.org/v2/guide/syntax.html#%E7%94%9F%E3%81%AE-HTML

XSSの危険性に問題がなければ非表示すれば大丈夫です。

```vue
<template>
  <v-main>
    <!-- eslint-disable-next-line vue/no-v-html -->
    <h1 v-html="title" />
  </v-main>
</template>
```

もしくはHTMLがなければv-textかマッシュタグ構文に書き換えればOKです。

## ESLint側のルールで非表示にする
毎回`<!-- eslint-disable-next-line vue/no-v-html -->`を書くのは大変なのとソースが汚くなるので、Nuxt内にある.eslintrc.jsのrulesを追加することで非表示にすることもできます。

```.eslintrc.js
module.exports = {
　-- 省略 --
  rules: {
    'vue/no-v-html': 'off'
  }
}
```

これでコードの記入時やyarn dev時にwarnの出力がなくなりました。
【Power Automate Desktop】変数のデータ型のプロパティ一覧

要するにMicrosft Docs　

https://docs.microsoft.com/ja-jp/power-automate/desktop-flows/datatype-properties　

に書いてある内容まんまなのだが、毎回参照するのは面倒かつ、このサイト翻訳が滅茶苦茶適当で変数名まで日本語になってしまっているので、自分用にわかりやすくまとめた備忘録です。:cop_tone1:

## Power Automate Desktop における変数のプロパティ

> プロパティの値には、次の表記法を使用して直接アクセスできます: %VariableName.PropertyName%

変数名.<b>プロパティ名</b>
で、それら変数のデータ型に紐づいた特定の情報を取得することが出来る。

---

### テキスト型
|プロパティ|内容|
|---|---|
|Length|保存されたテキストの長さ (文字数) 
|IsEmpty|変数が空の場合は真、一部の文字が含まれている場合は偽
|ToUpper|アルファベットをすべて大文字に
|ToLower|アルファベットをすべて小文字に
|Trimmed|両端にある空白を取り除いた文字列を返す
---
### リスト型
|プロパティ|内容|
|---|---|
Count|リストに格納されている項目の数
---
### 日付型
|プロパティ|内容|
|---|---|
Year|値の年の部分
Month|値の月の部分
Day|値の日の部分
Hour|値の時の部分
Minute|値の分の部分
Second|値の秒の部分
DayOfWeek|日の名前 (日曜、月曜など)
DayOfYear|その年の1月1日からの日数
---
### ファイル型
|プロパティ|内容|
|---|---|
Fullname|ファイルのフルパスです。
RootPath|ファイルのルート パスです: 例 C:\。
Directory|ファイルが格納されているディレクトリです。
Name|拡張子を含むファイル名です。
NameWithoutExtension|拡張子のないファイル名です。
Extension|ファイルの拡張子です。
Size|ファイルのサイズをバイト単位で指定します。
CreationTime|ファイルが作成された日付です。
LastAccessed|ファイルに最後にアクセスした日付です。
LastModified|ファイルを最後に修正した日付です。
Exists|このプロパティは、ファイルが存在する場合は真、ファイルが存在しない場合は偽となります。
IsEmpty|このプロパティは、ファイルが空の場合は真、ファイルが空でない場合は偽となります。
IsHidden|このプロパティは、ファイルが非表示の場合は真、ファイルが表示されている場合は偽です。
IsSystem|このプロパティは、ファイルがシステム ファイルの場合真、そうでない場合は偽です。
IsReadOnly|このプロパティは、ファイルが読み取り専用の場合は真、そうでない場合は偽となります。
IsArchive|このプロパティは、ファイルがアーカイブの場合は真、そうでない場合は偽となります。
---
### フォルダ型
|プロパティ|内容|
|---|---|
Fullname|フォルダーのフルパスです。
RootPath|フォルダーのルート パスです: 例 C:\。
Parent|フォルダの親ディレクトリです。
Name|フォルダーの名前。
CreationTime|フォルダーが作成された日付です。
LastModified|フォルダーを最後に修正した日付です。
Exists|このプロパティは、フォルダーが存在する場合は真、フォルダーが存在しない場合は偽となります。
FilesCount|フォルダー内のファイル数です。
FoldersCount|フォルダー内のフォルダの数です。
IsEmpty|このプロパティは、フォルダーが空の場合は真、フォルダーが空でない場合は偽となります。
IsHidden|このプロパティは、フォルダーが非表示の場合は真、フォルダーが表示されている場合は偽です。
---
### メールメッセージ型
|プロパティ|内容|
|---|---|
MailFolder|メールメッセージが取得される名前のフォルダーです。
Uid|メッセージの一意識別子。
From|メールメッセージの送信者です。
To|メッセージの受信者を含む値のリストです。
CC|メッセージの追加受信者を含む値のリストです (カーボン コピー)。
Date|メッセージが送信された日時です。
Subject|メッセージの件名です。
Body|メッセージの本文です。 本文はプレーンテキストまたは HTML 形式にすることができます。
BodyText|前のプロパティに HTML が含まれている場合、このプロパティにはプレーンテキスト形式のメッセージ本文が含まれます。
Attachments|メール メッセージの保存された添付ファイルを表すファイルのリストです (存在する場合)。
---
### データテーブル型, データ行型
|プロパティ|内容|
|---|---|
RowsCount|データ テーブルの行数です。
Columns|データ テーブルの列の名前を含むリストです。
IsEmpty|このプロパティは、データ テーブルが空の場合は真、要素が含まれている場合は偽です。

|プロパティ|内容|
|---|---|
ColumnsCount|データ行が保持する列の数です。
ColumnsNames|データ行のヘッダーを含むリストです。
---

他にも多数ありますが、普段使いする可能性があるのはこの程度かな。

意外と知らない人がいるのですが
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545378/a3faa6c4-566b-fdc8-3219-34fd1132f04c.png)
〇印のある{x}をクリックすると、生成されている変数の各プロパティを一覧形式で見ることができ、そこから選択できます。
GitHub Actions docker-compose exec で the input device is not a TTY エラー

GitHub Actionsでdocker-composeでコンテナ内にあるLaravelのartisanコマンドを実行させたい時にエラーになったので解決方法を残します。

## 環境

- Ubuntu: 20.04.2 LTS (Focal Fossa)
- Docker Client: 20.10.6+azure
- Docker Server Engine: 20.10.6+azure

## .github/workflows/integration-laravel-testing.yml

```yml:.github/workflows/integration-laravel-testing.yml
name: Laravel Testing

on:
  pull_request:

jobs:
  laravel-testing:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Docker Version
        run: docker version

      - name: Docker Compose Build and Up
        run: |
          docker-compose build app web db
          docker-compose up -d app web db

      - name: Docker Compose Process
        run: docker-compose ps -a

      - name: PHP, Composer Version
        run: |
          docker-compose exec app php --version
          docker-compose exec app composer --version
```

## 実行結果(エラー)

![ScreenShot 2021-05-20 10.15.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/92bdb8dd-a65a-3ac8-5e40-68b6d5a12385.png)

```
Run docker-compose exec app php --version
  docker-compose exec app php --version
  docker-compose exec app composer --version
  shell: /usr/bin/bash -e {0}
the input device is not a TTY
Error: Process completed with exit code 1.
```

`the input device is not a TTY` は一体なんなんだ...🤔
直訳すると `入力デバイスはTTYではありません`

## ヘルプ

```
$ docker-comopse exec -h

    -T                Disable pseudo-tty allocation. By default `docker-compose exec`
                      allocates a TTY.
```

`-T` オプションを付けると疑似ttyの割り当てを無効化してくれるみたい。
試しに `-T` を付けてみる。

```
      - name: PHP, Composer Version
        run: |
          docker-compose exec -T app php --version
          docker-compose exec -T app composer --version
```

## 実行結果(成功)

![ScreenShot 2021-05-20 10.20.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/a1e179ab-0bbe-7b76-1b85-1892d6aa4915.png)

## 調べてみる

- [GitHub Actionsでdocker-composeを使う](https://www.nullpo.io/2020/05/11/git-github-actions-docker-compose)

`COMPOSE_INTERACTIVE_NO_CLI=1` の環境変数を設定しても解決できるみたい

そもそもttyとは？

- [ttyとは？](https://qiita.com/hoge_5555/items/f677f9ec7cd859380426)

`仮想ファイルで出入力を扱うデバイス`らしい。
GitHub Actions上だとttyが割り当てられないのかな？詳しい人教えてください🙏

```
$ docker run -it ubuntu bash
```

`docker run` するときは明示的に `--interactive` と `--tty` を指定するよね🤔
`docker-compose exec` の時はデフォルトでttyが割り当てられるっぽい。

よくわかってないけど、とりあえず動くのでヨシ！
OnAppearがForm内のPickerでの画面遷移ごときで再発火して困ってる問題


ある入力済みデータ(student)を修正するEdit画面を作っていました。
@EnvironmentObjectに登録済み内容を代入し、編集後にはSaveボタンで保存する感じです。

Form内のPickerでは画面遷移して選択する形になると思うんですが、
以下のような形だと、Pickerで選択して戻って来たときにOnAppearがまた発火して、先にselected.nameを修正していても、それが元のデータで上書きされてしまいます。

```swift:
import SwiftUI

struct EditView: View {
    @EnvironmentObject var selected: Selected
    @ObservedObject var student: Student
    ...
    var body: some View {
        VStack{
            Form{
                Picker() //ここに入って戻ってくると←またOnAppearが発火する
            }
            ChildView() //このViewでselected.nameを編集
            ... // Saveボタンとか
        }
        .OnAppear(perform: {selected.name = student.name})
}

```
そこで１つ別の変数(@State var name)を持たせておいて、Disapear時には一時的にそっちに入れておくことで回避しました。

```swift:
import SwiftUI

struct ContentView: View {
    @EnvironmentObject var selected: Selected
    @ObservedObject var student: Student
    @State var name: String

    init(student: Student){
       _student = ObservedObject(initialValue: student)
       _name = State(initialValue: student.name) 
    }
    var body: some View {
        VStack{
            Form{
               Picker()
               ...
            }
            ChildView() //このViewでselected.nameを編集
       　　  ... // Saveボタンとか
        }
        .OnAppear(perform: {selected.name = name})
        .OnDisppear(perform: {name = selected.name})
}

```
[C#] BrotliEncoder/BrotliDecoderの使い方

# この記事の目的

C#でBrotliEncoder/BrotliDecoderを使った際に苦戦したので、試行錯誤の結果を自分以外の人に共有したい。

# 前提条件

- .Net 6を想定。
- エンコードとデコードのInputは`ReadOnlySequence<byte>`、Outputは`IBufferWriter<byte>`とする。

# サンプルコード

https://github.com/lyrise/brotli-sample-cs

## Compress
```cs
public static void Compress(ReadOnlySequence<byte> sequence, IBufferWriter<byte> writer)
{
    using var encoder = new BrotliEncoder(11, 24);

    var reader = new SequenceReader<byte>(sequence);

    for (; ; )
    {
        var status = encoder.Compress(reader.UnreadSpan, writer.GetSpan(), out var consumed, out var written, false);
        if (status == OperationStatus.InvalidData) throw new Exception("invalid data");

        reader.Advance(consumed);
        writer.Advance(written);
        if (status == OperationStatus.Done) break;
    }

    for (; ; )
    {
        var status = encoder.Compress(ReadOnlySpan<byte>.Empty, writer.GetSpan(), out _, out var written, true);
        if (status == OperationStatus.InvalidData) throw new Exception("invalid data");

        writer.Advance(written);
        if (written == 0) break;
    }
}
```

## 訂正 (2022/10/08)
neueccさんにご指摘いただき、Compressが正しく処理できていないことが分かりました:bow_tone1:

`status`が`OperationStatus.Done`なら圧縮完了だと理解していたのですが、正しくは

> The entire input buffer has been processed and the operation is complete.

とドキュメントにも記載されている通り、inputの処理が完了したのみで、flush処理を別途行う必要がありました...

neueccさんありがとうございました:bow_tone1:

## Decompress

```cs
public static void Decompress(ReadOnlySequence<byte> sequence, IBufferWriter<byte> writer)
{
    var reader = new SequenceReader<byte>(sequence);

    using var decoder = new BrotliDecoder();

    for (; ; )
    {
        var status = decoder.Decompress(reader.UnreadSpan, writer.GetSpan(), out var consumed, out var written);
        if (status == OperationStatus.InvalidData) throw new Exception("invalid data");

        reader.Advance(consumed);
        writer.Advance(written);
        if (written == 0) break;
    }
}
```

# ハマったポイント

- `OperationStatus.DestinationTooSmall`はエラーというよりも、`destination`に最大まで書き込んだというお知らせなので、新しい`destination`を指定すればよい。
- ~~[BrotliEncoder.Compress](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.compression.brotliencoder.compress?view=net-5.0)で`isFinalBlock`にfalseを指定した場合、Decompress時にデータの末尾になっても`OperationStatus.Done`ではなく`OperationStatus.NeedMoreData`が常に返ってくる。~~ -> isFinalBlock: trueで最後に処理すればOKでした

# リンク

- https://docs.microsoft.com/ja-jp/dotnet/api/system.io.compression.brotliencoder
- https://docs.microsoft.com/ja-jp/dotnet/api/system.io.compression.brotlidecoder
React入門でつまづいた ～function App()とclass App extends Componentの違い～

# はじめに

Reactを勉強しているとき、分からなかったことがいくつかありました。この文書では、その中でも「function App()とclass App extends Componentの違い」について調べたことをまとめました。初学者の文書ですので内容に誤りがあるかもしれません。ですから、ご参考程度にお読みください。

もし、あなたが私と同じように雑多な情報しか得られなくて困っているなら、Reactの公式ドキュメントを読むことを強くお勧めします。正しい情報がすごく分かりやすくまとめられています。不幸なことに、私が受講したオンラインコースではそのような案内がありませんでした。正直、この公式ドキュメントの存在を知っていれば受講しなかったと思います。

Reactの公式ドキュメント
https://ja.reactjs.org/docs/hello-world.html

# 結論

__どちらも意味は同じです。__

function App()と書くと、ReactではAppが関数コンポーネント(functional component)として扱われます。Javascriptでは関数も1つのオブジェクトですが、関数コンポーネントは、React要素を返すオブジェクトです。引数としてpropsを受け取ります。propsはプロパティ(properties)の省略形で、JSXに書かれている属性情報などを親のコンポートネントから子のコンポーネントに渡すために使われます。propsはimmutable(イミュータブル, 不変)なオブジェクトですので、その中身を後から変更することはできません。

class App extends Componentと書くと、ReactではAppがクラスコンポーネント(class component)として扱われます。Javascriptではクラスも1つのオブジェクトですが、クラスコンポーネントもReact要素を返すオブジェクトです。propsはthis.propsで参照することができます。

__機能的な違いもなくなったようです。__

時間経過やユーザ操作などによって内部状態(state)が変化したとき、その状態変化によって出力を変更したければ、クラスコンポーネントを使うように案内されていたことがありました。しかし、2019年2月16日にReact16.8が公開されてからは、関数コンポーネントを使ってもReact Hooksという仕組みを用いて状態変化による出力変更を実装できるようになりました。よって、今では機能的な違いがなくなったように見えます。

__どちらを使っても大丈夫ですが、関数コンポーネントの方がシンプルです。__

公式サイトに、今後もクラスコンポーネントをなくす予定はないと書いてありますので、クラスコンポーネントを使い続けても問題はないでしょう。

> React からクラス型コンポーネントを削除する予定はありません。

フックの導入 (「互換性のない変更はありません」の節)
https://ja.reactjs.org/docs/hooks-intro.html

しかし、新規プロジェクトでわざわざクラスコンポーネントを使う必要はありません。関数コンポーネントの方がシンプルに書けるからです。コンストラクタを書いたりstateに毎回thisを付けてthis.stateにしたりとクラスコンポーネントは面倒なことが多いのですが、関数コンポーネントを使えばよりシンプルに書けます。クラスコンポーネントは古いプロジェクトで使わざるを得ないときに、必要に応じて勉強するのが良いようです。


# もっと深く理解したい人へ

関数コンポーネント、クラスコンポーネント、props
https://ja.reactjs.org/docs/components-and-props.html

時計を毎秒更新する方法（クラスコンポーネントとstateを使う方法）
https://ja.reactjs.org/docs/state-and-lifecycle.html

ボタンでカウンターの値を増やす方法（関数コンポーネントとHookを使う方法）
https://ja.reactjs.org/docs/hooks-overview.html