OmniAICreator/Qiita-1.07M huggingface dataset:
【Qiita注意報】投稿画像は勝手に再圧縮されます（ただし、原画像も保持）

:sunflower::sunflower::sunflower: 追記２（ここから） :sunflower::sunflower::sunflower:2022-08-03

　一部、勘違いしていることがありました。申し訳ありません。**投稿画像は恒久的に圧縮され、オリジナルは破棄されてしまっているものと思い込んでいましたが、そうでもなさそうです。**

　Windows10 の Microsoft Edgeでは、画像上で右クリックし「名前を付けて画像を保存」したときには圧縮されたwebpで保存されます（これは前言どおりです。しかし、Qiitaの一部の記事の画像では、gifのままで保存できるものもあるようです）

　一方、 **画像上で左クリックし、画像単独の画面にしたのち、右クリックで「名前を付けて画像を保存」したときには、アップロードしたままの拡張子の画像が保存できます**（jpg, png, gif で確認。tifでは未確認）。 ヘッダー部の名前は変わっていますが、手元に保存していたファイルと同一容量なので **欠損はないようです。** 

　 **後者のダウンロード方法を見逃していました。私としては、これさえできれば、Qiitaの今のままの運用方法で何ら差し支えありません。** 

:sunflower::sunflower::sunflower: 追記２（ここまで） :sunflower::sunflower::sunflower:

:cherry_blossom::cherry_blossom::cherry_blossom: 追記（ここから） :cherry_blossom::cherry_blossom::cherry_blossom:2022-08-02

　2022-07-21 頃から、ヘルプは下記のように更新されています。

　「なお、過去には一定の容量を超えた場合自動で圧縮する、といった仕様もありましたが現在は撤廃されています。」は削除され、「アップロードされた画像は、自動的に順次最適化が行われます。」が追加されています。

　これで、実際の運用方法との矛盾は解消されましたが、説明があまり親切ではありません。

　Qiitaの言う「最適化」とは、webpフォーマットへの強制変換による容量の圧縮のことです。私としては、投稿したままのフォーマットの方が「最適」だったのですが・・・。なお、圧縮されると投稿時の gif, jpeg, png, tiff の拡張子は痕跡も残りません。全てwebp拡張子に変わってしまいます。


　現在、ホームページの下部の「ヘルプ」をクリックし、「記事の投稿」の「画像のアップロード方法」をクリックすると下記が表示されるようになっています。

>**アップロードできる画像の容量制限**
>ファイル単体で10MBまでの画像ファイルをアップロードすることが可能です。
>画像ファイルは月に合計100MBまでしかアップロードできません。
>制限を超えてしまった場合は次の月までお待ちください。
>
>**アップロード可能な画像**
>アップロード可能な画像は、 gif , jpeg , png , tiff です。
>
>**画像の最適化について**
>アップロードされた画像は、自動的に順次最適化が行われます。

:cherry_blossom::cherry_blossom::cherry_blossom:追記（ここまで）:cherry_blossom::cherry_blossom::cherry_blossom:

　うしろに引用している Qiita の「画像のアップロード方法」によれば、投稿者が容量制限を守って投稿している限り、画像ファイルの再圧縮はされないように受け取れます。

　しかし、私が投稿した画像ファイルを調べてみると、容量的に何の問題もない jpg や png フォーマットの画像がすべて webp フォーマットで再圧縮されてしまっています（７月６日現在）。７月１日には、半分程度は jpg や png のまま残っていたのですが、再圧縮がどんどん進んでいるようです。なお、アニメgifだけは今でもそのまま残っています。

　Qiitaをクラウド並みの保管場所として信用していたので、投稿画像の自PCでの管理がいいかげんで、「原画像の喪失！」かと慌てました。しかし、なんとか探し出して大切に保管できたので一安心ではあります。ついでに、Qiitaのオンラインのエディタ機能で投稿していた本文は、自PC内に控えも無かったのでダウンロードして保管しました。

　Qiitaのサポートへの質問メールとその回答も添付します。

**弊質問**

>過去の投稿に添付したpng, jpg画像の一部が、何故かwebpに変わってしまっていますが、強制的に変換されてしまうようなQiitaの条件でもあるのでしょうか？　できれば、投稿したときのフォーマットのまま公開していただいた方が色々と都合が良いのですが・・・。

**Qiita回答**

>Qiitaに投稿された画像は転送量の削減のため、自動的に順次最適化が行われております。
何卒ご了承くださいますようお願い申し上げます。

**Qiita のチートシートでの説明**

「Markdown記法 チートシート」から
　　最下段の「ヘルプ」をクリック。
　　　～「記事の投稿」をクリック。
　　　　～「画像のアップロード方法」をクリックすると下記が表示されます。

>**アップロードできる画像の容量制限**
>ファイル単体で10MBまでの画像ファイルをアップロードすることが可能です。
>なお、過去には一定の容量を超えた場合自動で圧縮する、といった仕様もありましたが現在は撤廃されています。
>画像ファイルは月に合計100MBまでしかアップロードできません。
>制限を超えてしまった場合は次の月までお待ちください。

>**アップロード可能な画像**
>アップロード可能な画像は、 gif , jpeg , png , tiff です。
プログラミング初心者の私がQiitaで質問したら起きたあるある①

# Qiitaで質問したら起きたあるある

私にはこんなことがあります。

アプリを制作していたら、突然望んでいないバグが生じる。

何が起きたんだ。

どうしよう...何とかしようと考える...解決できない...課題が進まない...Qiitaで質問しよう


すると...なぜか自分自身で解決方法が降りてくる。

## 気付いたこと
Qiitaで質問する際に私が気をつけていることが、そのまま正しいバグ対処方法になっていた。

①正解は何か。（目標の明確化）
②問題点の把握（目標と現状の比較、入手している情報の整理）
③原因の分析(なぜ問題が生じているのか思案)
④対処したこと

質問する前の私は、②で問題点を把握したつもりになって、③を抜かして、④に行くことが多い。

## とりあえず思いつくままに記事を書いて見たわけだが
初心者の私は、バグが生じた際に、”どうしよう”から考える癖があるようだ。
その結果、①を考えて、④に向かう傾向がある。（②③を考えていないわけではないが、
結果的に考えていないことと同じである。）

質問を投稿した後にいただく他のユーザーさんからのコメントの多くが、”なぜ”にあたる
②③を知るための質問が多いことからも、私の中で②③に対する意識が低いことが客観的に
分かった。

これからは、行き当たりばかりの対処ではなく、①②③を正確に人に伝えることができるまで、
思考を整理した段階で、④に取り掛かろうと思う。

それでも解決できない場合は、他のユーザーさんに助力をお願いしようと思う。
Windows10からubuntu22.04のPCへリモートアクセス

Windows10のPCからUbuntu22.04のPCへリモートアクセスしてみた
[（Ubuntu20.04の画面共有はこちら）](https://qiita.com/suginaga/items/19c15b9ded16b2a1a672)
参考にしたサイト
[https://www.yokoweb.net/2022/05/03/ubuntu-22_04-desktop-rdp-remote/](https://www.yokoweb.net/2022/05/03/ubuntu-22_04-desktop-rdp-remote/)
# Ubuntu側でやること
### 画面共有設定
画面を右クリックして`Display Setting`を選択
右上のSharingのトグルボタンをクリックしてONにし、`Remote Desktop`をクリック
![img20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666944/0db33fe1-64b2-318a-c86e-49abe0e54552.png)
`Remote Desktop`と`Remote Control`のトグルボタンをON、ユーザー名とパスワードを入力し閉じます
![img21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666944/20655dcd-2664-1fcf-e2d8-69d045bf38a6.png)
右上のSharingのトグルボタンと`Remote Desktop`がONになっていればOK
![img22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666944/50b70566-076d-a49d-5145-cd83ca4c8fda.png)

# Windows側でやること
### リモート接続設定
画面左下のスタートボタンより`Windowsアクセサリ`を選択し
![img23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666944/bda181e9-f9aa-1b10-130f-b31bd0d974c1.png)
`リモートデスクトップ接続`を選択
![img24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666944/d33e029b-1dae-241b-d29f-b680ae6afc40.png)
Ubuntuのコンピューター名を入力
![img25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666944/a133cc60-b269-84aa-7d00-6ee73b48d9a6.png)
ユーザー名とパスワードを入力し`OK`をクリック
![img26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666944/9309620b-862b-13ed-3f49-906c8578d56b.png)
Ubuntuの画面が表示され、操作もできます。
![img27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666944/a925fb94-23f6-23e9-a836-c5d6e869faf6.png)
【Laravel】Eloquentモデルでデータ保存・取得時に値を加工する

配列を文字列として保存したり、取得時に文字列から配列にしたいといったように、DBからのデータ取得・保存時に値を加工するやり方を紹介します。
## Eloquentモデルで値を加工する
`Eloquentモデル`内に下記の記述をすることで値の取得・保存時に加工を自動で行うことができます。
```php 
    // Eloquentで値を取得する際に自動で呼ばれる
    // カラム名はアッパーキャメルケース
    public function getカラム名Attribute($value)
    {
        // 値を加工する処理

        // 加工後の値をリターン
        return 加工後の値
    }

    // Eloquentで値を保存する際に自動で呼ばれる
    // カラム名はアッパーキャメルケース
    public function setカラム名Attribute($value)
    {
        // 値を加工する処理

        // Eloquentモデルが持つattributeプロパティに加工後の値をセット
        // リターンは必要ない
        $this->attributes['カラム名'] = 加工後の値
    }
```

**`getカラム名Attribute()`はデータの取得時に呼ばれます。`value`が取得される値なので`value`を加工してリターンします。**
**`setカラム名Attribute()`はデータの保存時に呼ばれます。加工後の値を`Eloquentモデル`の`attribute`プロパティに、カラム名をキーとして加工後の値をセットします。この時リターンは必要ありません。**

以上で、Eloquentでのget()やfind()でデータ取得する際に加工された値を取得でき、save()などで加工された値を保存できるようになります。

## 単にキャストをしたい場合
`Eloquentモデル`内に下記の記述をすることで値の取得・保存時に指定した型に自動でキャストされます。
```php
    protected $casts = [
        'カラム名' => '型名',
    ];
```

## 参考
[Laravel 8.x Eloquent：ミューテタ／キャスト](https://readouble.com/laravel/8.x/ja/eloquent-mutators.html)
【命名】今からおまえの名前はFooBarだ

# 何についての記事か

システム開発における命名の話。

:::note warn
具体的な名称やコードは、実際の状況とは異なる形で例示しています。
重要なのはその詳細ではないので、そこについてはご容赦ください。
:::

先日私は、あるプロダクトで次のように命名した。

```php
class FooBar {
}
```

ひどい名前でしょう。
何故このような選択をしたのか、その経緯を説明します。

# 背景

元々このクラスは別の名称でした。
仮に支払いを表す`Payment`とでもしておきましょう。そしてシステムの支払い機能で使用されていました。

```php:以前の状態（仮）
class Payment {
}
```

FooBarよりはちゃんとした名前ですね。
　
　
「支払い機能**以外**でも使用されている」という点に目をつぶれば。
　
　
この`Payment`クラスはシステムの様々な機能で利用されていたのです。
会員登録でも`Payment`、お問い合わせでも`Payment`。
とても適切な名称ではありません。

そして先日、支払い機能を改修するタイミングで、支払い機能ではこの`Payment`クラスは使用しないようになりました。

# 君の名は

いよいよ肝心の支払い機能で`Payment`クラスを使用しないことになり、私はこの名称を変更する機会だと考えました。

そして考えます。適切な名称は何なのか。

　
君の名は・・・

　
名前は・・・

　
わからん。

そもそも何故こうした状況になっているのかというと、単に「コードを流用したいため」にバラまかれたのは想像に難くありません。

つまり正しさはすでに失われたので「適切な名称は存在しない」と結論付けました。

# 命名する

とはいえ`Payment`は明らかに適さないので、何か別の名前を付ける必要があります。

こういう時に`Common`や`Util`が浮かびそうですが、私はそれを避けました。これらの当たり障りのない名称は「とりあえずこれで良い」という悪い流れを生みます。

また意味のないものに、さも意味ありげな名前を付け、命名した気になるのを避けたかったのです。

そうして悩んだ結果、最終的に`FooBar`クラスと命名することを選択しました。
（残念ながらこれを正しい形にするタイミングは今ではない、という判断も含めて）

# まとめ

`FooBar`という命名が正しかったのかはさておき、重要と考えるのは「**良いも悪いも正しく伝える必要があり、それを誤魔化すべきではない**」という点です。

私は設計で妥協したり誤魔化したりした結果がどうなるか、実際に見てきましたし今も見ています。
それを踏まえて、今回は「適切な名前がない」ことを示すような命名を選択しました。

> "この責任を果たすことは「戦い」に足を踏み入れることを意味する。"
> "保護すべきソフトウェアに対する責任がある。それがあなたの役割であり、義務である。それが、あなたが雇われている大きな理由だ。"[^1]
> -- Robert C. Martin（ボブおじさん）
[^1]:『Clean Architecture』 アーキテクチャの戦い

　
　
　
　
余談ですが、良くないのは名称だけ、なんてことはなく、この何倍も大変なレガシーコードとの戦いがありました。
全くもって不毛な戦いでしかなかったので、何かの役に立てば幸いです。

ー完ー
Dockerコンテナのactix-webをherokuで動かそうとしたらError R10 (Boot timeout)が出た

# エラー内容

acitx-webの公式サイトの[Getting Started](https://actix.rs/docs/getting-started/)をdockerコンテナで動かしていました。ローカル環境では動いていたのですが、herokuにデプロイするとApplication errorが出て正常に動作しませんでした。

![Screenshot from 2022-07-06 13-02-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271649/f5b57f3a-c633-381e-98dd-7644802b3356.png)

`heroku logs --tail`コマンドで確認すると`Error R10 (boot timeout)`というエラーが出ていました。

```sh
$ heroku logs --tail
;; 抜粋
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
Stopping process with SIGKILL
Process exited with status 137
State changed from starting to crashed
```

herokuの公式サイトで調べるとherokuでは環境変数`$PORT`がデフォルトで設定されていて、dyno（heroku上で動いているアプリコンテナ）はこの環境変数`$PORT`で表されるポート番号でリッスンする必要があるみたいです。

> **webサーバー**
> Heroku の外部では、Web アプリが Web サーバーコンテナの内側で実行されることがあります。たとえば、PHP アプリが Apache HTTPD 内部でモジュールとして実行されたり、Java アプリが Tomcat 内部で実行されたりします。
> 
> Heroku では、アプリは完全に自己完結型です。Web サーバーによる実行環境へのランタイムインジェクションを使用して Web 対応サービスをつくり出すのではありません。各 Web プロセスがポートに結合して、そのポートで着信するリクエストをリスンするだけです。結合する相手のポート​は、Heroku により PORT​ 環境変数として割り当てられます。

https://devcenter.heroku.com/ja/articles/runtime-principles#web-servers

> **ローカル環境変数**
> Dyno Manager により、アプリケーション内でアクセスできる多数のデフォルト環境変数が設定されます。
> - dyno が Web dyno である場合は、$PORT​ 変数が設定されます。 dyno が受信リクエストを受け取るには、このポート番号にバインドする必要があります。

https://devcenter.heroku.com/ja/articles/dynos#local-environment-variables

> **R10-ブートタイム**
> Webプロセスは、割り当てられたにバインドするのに60秒以上かかりました$PORT。これが発生すると、dynoのプロセスが強制終了され、dynoがクラッシュしたと見なされます。クラッシュしたdynoは、dynoマネージャーの再起動ポリシーに従って再起動されます。

https://devcenter.heroku.com/articles/error-codes#r10-boot-timeout

# 修正

環境変数`$PORT`を読み込んできてその値をポート番号としてバインドするようにしました。ローカル環境で環境変数`$PORT`がない場合でも動かせるようにデフォルトで8080を設定するようにしています。

```diff_rust
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
+ use std::env;

#[get("/")]
async fn hello() -> impl Responder {
    HttpResponse::Ok().body("Hello world!")
}

#[post("/echo")]
async fn echo(req_body: String) -> impl Responder {
    HttpResponse::Ok().body(req_body)
}

async fn manual_hello() -> impl Responder {
    HttpResponse::Ok().body("Hey there!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
+    let port = env::var("PORT")
+        .unwrap_or_else(|_| "8080".to_string())
+        .parse()
+        .expect("PORT must be anumber");

    HttpServer::new(|| {
        App::new()
            .service(hello)
            .service(echo)
            .route("/hey", web::get().to(manual_hello))
    })
-   .bind(("0.0.0.0", 8080))?
+   .bind(("0.0.0.0", port))?
   .run()
    .await
}
```

# 正常動作

修正してherokuにデプロイするとちゃんとHello world!が表示されるようになりました。

![Screenshot from 2022-07-06 12-14-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271649/e42e97f0-904b-e5b2-1dc5-a0874e6d9913.png)
Google Colaboratory で MATLAB を使う

# Google Colaboratory で MATLAB を使う

MATLAB は，（オンラインでいつでもどこからでも使えるとは宣伝しているが）無料では使えないらしい。

Google Colaboratory で octave を介すれば，ちょっと面倒な気はするが，無料で使えるようだ。

[Matlab in Google Colab.ipynb - Colaboratory](https://colab.research.google.com/drive/1gZMqezIqPlC6a4p4WJVsImErN3ri9NZL?usp=sharing)

以下のように行えばよい。

## octave のインストール

以下を行う。


```python
!apt install octave
```

もし，全くのはじめてなら数分かかるが，二回目以降はすぐ終わる。

二回目以降は，以下のような表示が出れば準備万端

    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    octave is already the newest version (4.2.2-1ubuntu1).
    The following package was automatically installed and is no longer required:
      libnvidia-common-460
    Use 'apt autoremove' to remove it.
    0 upgraded, 0 newly installed, 0 to remove and 49 not upgraded.

## 処理系の動作

Google Colaboratory で MATLLAB を使う基本は以下の 2 つを必要に応じて行うことである。

1. `%%writefile ファイル名.m` でコードをファイルに書き込む
2. `!octave -W ファイル名.m` で実行結果を表示する



## 例

二次元クロス集計表の独立性の検定を行う関数を定義し，それを用いて検定を行う例を示す。

まずは関数を定義する。MATLAB の慣例で関数名とファイル名を同じにするそうなので，`ChiSquareTest.m` に `ChiSquareTest` 関数の定義を書き込む。

この処理系の制約（?）で，期待されるとおりの処理結果にならない関数などがあるので，姑息な手段でエラー回避をする必要があるかもしれない。


```python
%%writefile ChiSquareTest.m

function [chisq, df, p] = ChiSquareTest(x)
    [nrow , ncol] = size(x);
    df = (nrow - 1) * (ncol - 1);
    colsums = sum(x, 1);
    rowsums = sum(x, 2);
    n = sum(rowsums);
    expectations = (rowsums * colsums) / n;
    Zscores = (x .- expectations) .^ 2 ./ expectations;
    % sum(Zscores, 'all') % エラー（このバージョンにはないため）
    % sum(Zscores, [1 2]) % なぜか適正に動かない
    chisq = sum(sum(Zscores));
    p = 1 - chi2cdf(chisq, df); % この環境では icdf はインストールされていないため
end
```

    Overwriting ChiSquareTest.m


他の言語ならば，上の ChiSquareTest.m に関数呼び出しのテストを書き込めるが，MATLAB ではそれではだめなようなので，テストは別のファイルに書き込む(`untitled.m`）。


```python
%%writefile untitled.m
x = [55 22 16 7; 40 32 24 4];
[chisq, df, p] = ChiSquareTest(x)
```

    Overwriting untitled.m


実行するために以下のようにする。


```python
!octave -W untitled.m
```

    chisq =  6.6385
    df =  3
    p =  0.084359


結果をきれいな書式で書き出す方法は，まだ探索していない。
私も上司や同僚にかけてもらって嬉しかった言葉を書いとく


この記事を読んで私も救われてる言葉があったなと思ったので書いとく

https://qiita.com/Fukushige_yuko/items/91e63049c23858c39889


連絡ありがとう！！　いいですね使わせてもらいます


# 私が嬉しかった言葉は「最近どう？」や「調子どう？」

結構っと頻繁に声をかけてもらう

上司とか偉い人とか、忙しい人とかになかなか話しかけにくい
若い頃はコミュ障だったりしたので、話しかけるのに時間がかかっていた

そんななか、頻繁に「調子どう？」っ特段なにかあるわけでもなく、頻繁に声をかけてくれる上司のお陰で相談とか気軽にできるようになった。

コミュニケーションってとにかくコンタクト回数を上げるだけで、好感度や信頼度が上がる

めんどくさいのでメールやチャットで過ごしがちだけど、直接顔を合わせて、相談に乗ってもらったり話をすることって大事だなって思います。

偉い人と対面のコミュニケーションを気軽にできるようになると、急ぎの仕事とか直接話しかけて優先的に対応してもらえますしね

<b>「調子どう？」って意味ないよなって思わず、人間関係構築のいりぐち思って使ってみて
【FLOCSS】初心者用　～環境構築から～

sassを勉強したけど、環境構築の仕方がわからな～という方必見！

#### VScodeをインストール
省略
####  【拡張機能】Live Sass Complierをインストール

その後、ファイルを選択して、下の青バーにあるWatchSassを押して、Sassの監視をオンにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314502/a299cc0d-9772-1907-f499-9212922e40f3.png)

そうすることで、scss形式でファイルと同じ内容のcssファイルが作成される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314502/0896803c-d67f-7dc2-5f55-985232009f5a.png)

ファイルの中身もしっかりとコンパイルされている！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314502/f9b8e2dd-08cf-cd04-a378-e27506dcc9dd.png)

他にもコンパイルの方法はたくさんありますが、

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
ご愛読ありがとうございました。
何か気づきや質問があれば、コメントお願いします。
新しい情報を取得するたび、更新していきます。

良ければ、LGTM、ストックよろしくお願いいたします！
回答で使う画像


# プレイグランド関係

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b42b4bc7-abab-d40f-c521-c4982ded8739.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/dd3ee7a1-31a3-265c-bd7e-289b846f9977.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/03344e46-27b2-40f9-9627-0fd954d87cda.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6b7fb57f-c7ff-2674-998d-a4a39025d65c.png)

# 開発者コンソール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/863cda6d-8b82-937d-a629-acf3fe41d109.png)
Unityでコントローラーの種別を識別する(InputSystem)

:::note info
2024/03/28追記：**本記事のリメイク記事を書きました。**  
実装アプローチや、対応デバイスの追加、デバイス変更時イベントの実装など、いろいろ追加/改善しているので、こちらもご確認ください。  

【Unity/InputSystem】新・操作中のコントローラーの種類を識別する - 猫茶の研究日誌  
https://nekocha.hatenablog.com/entry/2024/03/28/212705
:::

UnityでPCゲームを製作時、使用中のゲームパッドに応じたボタンガイドを作る際に困ったので、メモしておく。

InputSystemで、ゲームパッドの種別による違いを吸収してくれるのはありがたいが、
**「いまどのコントローラを使っているか？」** を確かめたいときがあるだろう。

PSコントローラなら「×で決定」、Xboxコントローラなら「Aで決定」、マウス&キーボードなら「左クリックで決定」と、自動で表示を切り替える処理を実装したいときとか... 

DualShockGamepad.current.IsPressed()のように書いて済めばよかったのだが、これは不可能だったので、
かわりに筆者がやってみた方法を紹介する。

# サンプルソース

早速サンプルソース。この手のものは結論ファーストが良いと最近思ってるので。

動作確認環境：Windows 10, Unity 2021.3.0f1

```csharp
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.DualShock;
using UnityEngine.InputSystem.XInput;

bool wasPressedLastFrame_DS = false;
bool wasPressedLastFrame_Xbox = false;
bool wasPressedLastFrame_PC = false;


// 以下を毎フレーム回す
// どのHIDが、直前フレームでキーが押されたかを確認する
void CheckIsPressedLastFrame()
{
    wasPressedLastFrame_DS = false;
    wasPressedLastFrame_Xbox = false;
    wasPressedLastFrame_PC = false;
    
    // DualShock(Dual Senceも含む模様)
    if (DualShockGamepad.current != null)
    {
        foreach (var key in DualShockGamepad.current.children)
        {
            if (key.IsPressed())
            {
                wasPressedLastFrame_DS = true;
                break;
            }
        }
    }
    // Xbox
    if (XInputController.current != null)
    {
        foreach (var key in XInputController.current.children)
        {
            if (key.IsPressed())
            {
                wasPressedLastFrame_Xbox = true;
                break;
            }
        }
    }
    // PC(マウス＆キーボード)
    if (Keyboard.current != null)
    {
        foreach (var key in Keyboard.current.children)
        {
            if (key.IsPressed())
            {
                wasPressedLastFrame_PC = true;
                break;
            }
        }
    }
}
```


# 解説

「いま使われているか？」は、**直前のフレームでいずれかのボタンが押されたか**で判別する。
このために、**「毎フレーム、それぞれのデバイスについて、すべてのボタンの状態を確認する」** という処理が必要である。


## それぞれのデバイス種別ごと、直近に有効であるデバイスを取得する。
Xboxコントローラなら、```XInputController.current``` で取得できる。
PSコントローラなら```DualShockGamepad.current```といった具合である。

## すべてのボタンの状態を確認する。
InputSystemでは、ゲームパッドそのものからボタンなど、様々なものが「InputControl」抽象クラスを継承している。
このInputControlは親子構造をなしていて、ゲームパッドの子(child)には、その各種ボタンが割り当てられている。

つまり、PSコントローラなら```DualShockGamepad.current.child```でボタン類の情報を取ってこれる。
幸いなことに、主要なボタン類は一通りゲームパッドの子(child)であるようなので、今回はこれを使う。

あとは、すべてのキーに対して```IsPressed()```でキーの状態を取ってくるだけでよい。
メソッド、インスタンスメソッド、クラスメソッドの違い

# 初めに
プログラミングの勉強を始めて３ヶ月ほど経ちますがよく似た言葉や似たニュアンスの多い言葉がよく登場するケースによく遭遇します。例えばjavascriptで言うと関数とメソッドなど。このようなケースに遭遇した際正確な違いを特定するために２〜３時間かかる時もあります。なので初学者の方に私が今回調査した内容を共有することで「無駄な時間」を少しでも減らし、皆さんの学習の手助けに少しでもなれたらと思いこの記事を作成しています。


# 目次
<!-- タイトルとアンカー名を編集 -->
1,メソッド、インスタンスメソッド、クラスメソッドとは？？
2,3つの違いまとめ

# 1.メソッドとは？
パソコンに元々あるショートカットみたいなもの。
ショートカットとは？⇨１つのボタンでたくさんの処理をしてくれる機能
例えば、『おはよう』という文章を作りこの文章を削除しようとした際
パソコンのデリートキーを「４回」連続で押す必要がある。
ただショートカットだとcommand + D を１回押せば１文全て一瞬で削除できる。

```.rb
 def season # ⇦メソッドを作成。その中に下の季節が入っている
   puts "spring"
   puts"summer"
   puts "fall"
   puts "winter"
 end
   season # ↑の季節を全て呼ぶにはメソッド名で呼べる　
          #出力結果　spring summer fall winter 

  end


```



# 1.インスタンスメソッドとは？
クラスの中で定義されたメソッドをインスタンスメソッドと呼ぶ


```.rb
class Year
 def season # ⇦インスタンスメソッドを作成。
   puts "spring"
   puts"summer"
   puts "fall"
   puts "winter"
 end
  year = Year.new    #変数の中にクラス名.newを代入する
  year.season      #インスタンスメソッドの呼び出し　変数.メソッド名
                     #出力結果　spring summer fall winter 
  end


```

# 1.クラスメソッド
メソッドを定義する際に
def クラス名.メソット名で定義する
```.rb
class Year
 def Year.season # ⇦クラスメソッドを作成。
   puts "spring"
   puts"summer"
   puts "fall"
   puts "winter"
 end
  Year.season      #クラスメソッドの呼び出し　クラス名.クラスメソッド名
                     #出力結果　spring summer fall winter 
  end


```


# ２、３つの違いまとめ

| メソッド名      |       記述方法|    呼び出し方   |
|:-----------------|------------------:|:------------------:|
| メソッド         |      def 好きな名前         |   メソッド名           |
| インスタンスメソッド       |  クラス内でdef 好きな名前          |            変数＝クラス名.new の後に変数.インスタンスメソッド名|
| クラスメソッド          |  クラス内でdef　クラス名.好きな名前            |       クラス名.メソッド名
低品質画像をレタッチ、機械学習モデル

# 低クオリティな画像を綺麗にしたい

![pexels-wisnu-phaewchimplee-11102632.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/5c24b54b-e4f2-bc86-52ef-490730d2d2f0.jpeg)
![1ea5d59a-e707-46d5-994c-5fcc9f6c0fa0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/c4c01251-bfb3-7646-fe2c-ecea6a57e8c2.png)

# 機械学習モデルで一発

AdaIntというモデルに画像を入力するだけでレタッチしてくれます。

https://github.com/ImCharlesY/AdaInt


# 使い方

リポジトリをクローンし、ReadMeの手順でセットアップスクリプトを実行、以下のコードで実行できます。

```shell
python adaint/demo.py adaint/configs/fivekrgb.py pretrained/AiLUT-FiveK-sRGB.pth input_image_path ioutut_image_path 
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
40代おじさん「pythonの変数を日本語で書いちゃおう」

python初心者のおじさんです
どっかで変数に日本語行けるって書いてるのを見た気がするので遊んでみました

```
猫 = 0
for i in range(10):
    猫 += 1
    print("猫がニャーと",猫,"回鳴いた")
```
```
猫がニャーと 1 回鳴いた
猫がニャーと 2 回鳴いた
猫がニャーと 3 回鳴いた
猫がニャーと 4 回鳴いた
猫がニャーと 5 回鳴いた
猫がニャーと 6 回鳴いた
猫がニャーと 7 回鳴いた
猫がニャーと 8 回鳴いた
猫がニャーと 9 回鳴いた
猫がニャーと 10 回鳴いた
```

f文字列を使ってみた
```
猫 = 0

for i in range(10):
    猫 += 1
    print(f"猫がニャーと{猫}回鳴いた")

猫がニャーと1回鳴いた
猫がニャーと2回鳴いた
猫がニャーと3回鳴いた
猫がニャーと4回鳴いた
猫がニャーと5回鳴いた
猫がニャーと6回鳴いた
猫がニャーと7回鳴いた
猫がニャーと8回鳴いた
猫がニャーと9回鳴いた
猫がニャーと10回鳴いた

```

これで変数名に困ったら日本語で書けばいいじゃん！！！って思ったけど、わけがわからなくなるからやめておいた方がいいな

でも、英語圏の人は英語で変数名決めて、英語で文字打つじゃない？混乱したりしないのかな？
Firebase AuthでSign in with Appleを使ってるアプリの開発者アカウントを移管したらログインできなくなる問題

Sign in with Appleを使っている方で開発者アカウントを移行する際は気をつけた方がいいという記事です．Firebase Authを使っている際の解決策はないです．（ご存じの方おられたら教えてください）

# 問題と発生の経緯

Sign in with Appleを使ったアプリをApp Storeで配信していました．以前は個人名義の開発者アカウントを使っていたのですが，法人化に伴って法人名義の開発者アカウントに移管しました．アプリを他の開発者アカウントに移管することをAppleでは「Appの譲渡（App Transfer）」と言うそうです．Appの譲渡の仕方については公式の[Appの譲渡の概要](https://help.apple.com/app-store-connect/#/deved688524f)をご覧ください．

Appを譲渡しても筆者は特に何の影響も受けませんでしたが，ユーザから「勝手にログアウトされた」「再ログインしようとしても従来のSign in with Appleアカウントでログインできなくなった」と報告がありました．

Sign in with Appleではユーザはメールアドレスを公開して登録するか，メールアドレスを非公開（プライベートアドレスが発行される）で登録するかが選べます．メールアドレスを公開して自分のアドレスで登録していたユーザには譲渡の影響がありませんでしたが，非公開にしていたユーザは全て再ログイン時に新しいアカウントに変更されてしまい，これまでのデータが表示されなくなりました．

# 問題の原因

前述のAppの譲渡の概要には以下のように書かれていましたが見落としていました．


>受取人に App を譲渡する前に行うデータ準備の一環として、データベース内に存在する各ユーザに対して譲渡 ID を生成する必要があります。この作業は、Apple が提供する REST サービスエンドポイントから行うことができます。

Sign in with Appleでは非公開メールアドレスのユーザのアドレスは譲渡時に引き継がれないようです．そのため，ユーザ毎に譲渡IDを用意して移管前のプライベートアドレスと移管後のプライベートアドレスを紐付ける必要がありました．

# どうすべきだったか

この問題へのApple公式の対処法は以下のページにあります．

- [Transferring your apps and users to another team](https://developer.apple.com/documentation/sign_in_with_apple/transferring_your_apps_and_users_to_another_team)
- [Bringing new apps and users into your team](https://developer.apple.com/documentation/sign_in_with_apple/bringing_new_apps_and_users_into_your_team)

これらの情報を参照してAppleが提供するREST APIから，譲渡前に譲渡IDを取得，譲渡後に新たなアカウントデータとの接続が必要です．


# Firebase Authでは対応できない？

調べた限りFirebase Authの機能としてはAppの譲渡時のためのサポート機能は用意されていないようでした．またfirebaseのadmintoolのようなサーバーサイド用管理ツールでも専用の機能はなさそうです．

Appleが用意しているREST APIを使えば上手くいく可能性がありますが，譲渡前作業を忘れた著者にはもう遅く，こちらでは確認していません．

# 感想

- 譲渡前はちゃんとドキュメントを読んで準備を忘れないようにしよう
FlutterのiOSシュミレーターで設定画面に遷移させる

最終的にはアプリ内からIOS設定画面に遷移できれば良いので。
![スクリーンショット 2022-07-06 12.16.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/da0a4f2b-3643-bab5-72d5-5cbd877fdcba.png)
まずは、[permission_handler](https://pub.dev/packages/permission_handler)を`dependencies`の中に最新版を書きます。
```pubspec.yaml
dependencies:
  permission_handler: ^XX.X.X <-latest
```
`flutter pub get`する前に下記２行を`Info.plist`内に追記と↓
`<key>PermissionGroupNotification</key>　　　
    <string>通知をするため</string>`
```ios/Runner/Info.plist
~省略~
<plist version="1.0">
<dict>
	<key>PermissionGroupNotification</key>　　　
    <string>通知をするため</string>
	<key>CFBundleDevelopmentRegion</key>
~省略~
```
`Podfile`内にも下記を追記します。
```ios/Podfile
~省略~
flutter_ios_podfile_setup

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)

    target.build_configurations.each do |config|
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
              '$(inherited)',

      'PERMISSION_NOTIFICATIONS=1',
      ]

    end

  end
end
```
一度、
```
flutter clean
```
してから
```
flutter pub get
```
します。
```
cd ios
```
あとは`ios`フォルダに移動して`pod install`すれば使えるようになります。
```
pod install
```
使用したい`dart`ファイルでインポートしてきて`openAppSettings`関数を呼べば遷移できます。 
```hoge.dart
import 'package:permission_handler/permission_handler.dart';

TextButton(
  onPressed: () async {
    openAppSettings();
  },
  style: TextButton.styleFrom(
    primary: Colors.blue,
  ),
  child: Text('設定を開く'),
),
```
[備忘用]laravel, php覚書

## 目的
忘れがちな関数や記法をストックしておく
```php
where('id', $id)
//と
find($id);
```

findの方がシンプルに書ける

```php
!is_null($a) ? $a : $b
//と
$a ?? $b
```

null合体演算子

```php
$model->attach($id);
```

中間テーブルを作成

```php
$model = Model::find($id)->update();
$model = Model::create($params);
```

作成/更新したデータを返すので、そのデータを再利用する時に使う。

```php
$arr = ['44' => 0];
dd(empty($arr)); //false

$arr = ['44' => ''];
dd(empty($arr)); //false

$arr = ['44' => false];
dd(empty($arr)); //false

$arr = ['44' => null];
dd(empty($arr)); //false
```

キーが設定されていてバリューがfalsyな値の時、empty()するとfalseが返る

```php
condition1 && condition2

!condition1 || !condition2 
```

&&の否定

```php
$collection = User::with('posts')->select('title'); //titleはpostsのカラム
```

これだと取れない。生sqlのjoinとは異なり、eloquentでは結合したテーブルのカラムを取得できない。

```php
$collection->pluck('key.value')
```

ドット区切りでpluckの引数を書くと、下の階層の要素を指定できる。
【FLOCSS】初心者用　～基礎から～

#### FLOCSSを初めて、使ってみたい人、必見！

FLOCSSを使っているサイト一覧
以下サイトを参考にしながら、これからのプロジェクトに活かしてみよう！

FLOCSS公式Git
https://github.com/hiloki/flocss

以下の手順で作業を進めていきます。
１．クラス名を考えながら、コードを書く
２．考えたクラス名を元に基本構造を作成
３.

#### １.まず、基本構造を作成

HTMLファイルを作成しながら、cssクラス名を考える

#### 2.考えたクラス名を元に基本構造を作成

以下の構造（例）を参考に作成

```
├── foundation
│   ├── _base.scss
│   └── _reset.scss
├── layout
│   ├── _footer.scss
│   ├── _header.scss
│   ├── _main.scss
│   └── _sidebar.scss
└── object
    ├── component
    │   ├── _button.scss
    │   ├── _dialog.scss
    │   ├── _grid.scss
    │   └── _media.scss
    ├── project
    │   ├── _articles.scss
    │   ├── _comments.scss
    │   ├── _gallery.scss
    │   └── _profile.scss
    └── utility
        ├── _align.scss
        ├── _clearfix.scss
        ├── _margin.scss
        ├── _position.scss
        ├── _size.scss
        └── _text.scss
```

### Style.scss には何を書く？
（各ディレクトリに_index.scssを書かない場合)
```
@use "foundation/_reset";
@use "foundation/_base";

@use "layout/_footer";
@use "layout/_header";
@use "layout/_main";
@use "layout/_sidebar";


@use "object/component/_button";
@use "object/component/_grid";
@use "object/component/_media";
@use "object/component/_title";


@use "object/project/_articles";
@use "object/project/_comments";
@use "object/project/_gallery";
@use "object/project/_profile";
@use "object/project/_section";


@use "object/utility/_align";
@use "object/utility/_clearfix";
@use "object/utility/_margin";
@use "object/utility/_typography";
```

上のファイルの様に、@importを使って、Sassファイルを呼び出して1つのCSSファイルにコンパイルさせます！


### 命名規則

#### プレフィックスをつける
layout なら、.l-, componentなら、.c- のように、属しているフォルダ名の頭文字と‐でプレフィックスを頭につける。

#### ファイル名はクラス名
ファイル名は省略しないことでだれでもわかるようにする。

#### BEM命名規則を採用

Block, Element, Modifier, 
例
```
<!--ボタン-->
<button class="c-button"></button>
<!--ボタンの色違い＋サイズ違いモディファイア-->
<button class="c-button c-button--blue c-button--small"></button>
```

Block-Element--Modifier

▼BEMの命名規則で参考になるページです▼
https://qiita.com/manabuyasuda/items/dbb76ed36970bec95470

https://qiita.com/takahirocook/items/01fd723b934e3b38cbbc

https://qiita.com/usagi-f/items/b4e56e765384c49d5d04


### ディレクトリの構成

ディレクトリの構成は以下になります。
・sassファイルとcssファイル。
・sassファイルの下にはLayout・Object・Foundationフォルダがあります。
・indexファイルはsassの各フォルダに入れる
・style.scssでそれぞれのフォルダを一括して読み込む

><b>indexファイルはsassの各フォルダに入れる</b>

例えば、以下のファイルがfuondationディレクトリ配下にあったとします。
・base.scss
・reset.scss

foundationの中にあるindexは以下の様に追記します。

```
@use "base";
@use "reset";
```
このように、_index.scssを使うことで、style.scssでそれぞれのフォルダを一括して読み込むことができます。


><b>style.scssはフォルダごとに一括して読みこむ</b>

```
@use "foundation";
@use "layout";
・・・
```

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
ご愛読ありがとうございました。
何か気づきや質問があれば、コメントお願いします。
新しい情報を取得するたび、更新していきます。

良ければ、LGTM、ストックよろしくお願いいたします！
windows の Docker login で  "Not enough memory resources are available" の対処法

## AWS ECR に push できない

```
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com
```
AWS ECRへイメージをプッシュしようとログインコマンドを実行するとエラーが発生

色々調べても解決しなかったが、stack overflowに投稿がありました。

https://stackoverflow.com/questions/60211263/docker-login-error-not-enough-memory-resources-are-available

どうやらwindowsの資格情報マネージャーがいっぱいでエラーになっているようです。

スタートメニューから資格情報マネージャーを起動し、不要な資格情報を削除すると上手くいきました。

## おまけ
一括削除する方法が見つからなかったため、[おーとくりっかー](https://forest.watch.impress.co.jp/library/software/autoclicker/)を使用して削除しました。
Kivyを使ってみた（Python）

# はじめに
KivyというGUIライブラリを作成するオープンソースのライブラリを使ってみたので、まとめました

https://kivy.org/#home

# 前提
・Pythonがインストールされていること
・Homebrewがインストールされていること
・MacOSのPCを使用すること

# Kivyのインストール
1.Kivyに必要な依存関係のあるものをインストールします
```
brew install pkg-config sdl2_image sdl2_ttf sdl2_mixer gstreamer
```

2.Cythonをインストールします
```
pip3 install -U Cython
```

3.Kivyをインストールします
```
pip3 install kivy
```

4.Kivyの日本語版をインストールします
```
pip3 install japanize-kivy
```

# 簡単なアプリ実行
1.sample.pyファイルを作成します
作成したファイルに下記コードをコピペしてください

```sample.py
from kivy.app import App
from kivy.uix.label import Label
import japanize_kivy

class Test(App):
    def build(self):
        return Label(
            text = "テスト実行",
            font_size = 60
        )

if __name__ == '__main__':
    Test().run()
```

2.動かしてみます
```
python3 sample.py
```

3.数分待ち、下記のような画面が表示されればOK
![スクリーンショット 2022-07-06 11.11.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/7edd7a14-1f7d-7dc8-e43b-cf1272d563aa.png)

# GUIアプリ作成
1.gui_apl.pyファイルを作成します
作成したファイルに下記コードをコピペしてください
```gui_apl.py
from kivy.app import App
import japanize_kivy
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.core.window import Window

Window.clearcolor = (1, 1, 1, 1)

# 画面
class Screen(App):
    def build(self):
        # 画面の設定
        self.window = GridLayout()
        self.window.cols = 1
        self.window.size_hint = (0.6, 0.7)
        self.window.pos_hint = {'center_x':0.5, 'center_y':0.5}

        # ウィジェットの追加
        self.window.add_widget(Image(source='sample.jpeg'))

        # ラベル
        self.Test = Label(
            # ラベルのテキスト
            text = 'サンプルアプリ',
            # フォントサイズ
            font_size = 40,
            # 文字色
            color = 'blue'
        )

        # ラベルを画面上部に追加
        self.window.add_widget(self.Test)

        # ボタンウィジェット
        self.button = Button(
            # ボタン上に表示させるのテキスト
            text = 'クリック',
            # 背景色
            background_color = 'blue',
            # サイズの設定
            size_hint = (1,0.5),
            # 文字色
            color = 'white',
            # フォントサイズ
            font_size = 30,
            # ボタンの背景色
            background_normal = ''
        )

        # ボタンをクリックした時の処理
        self.button.bind(on_press = self.callback)
        # ボタンを画面上に追加
        self.window.add_widget(self.button)

        # レイアウトをリターン
        return self.window

    def callback(self, instance):
        # ラベルのテキストを変更
        self.Test.text = 'クリックされました'

if __name__ == '__main__':
    Screen().run()
```

2.動かしてみます
```
python3 gui_apl.py
```

3.画面が開いて、ボタンクリックイベントが動けばOK
Salesforce商談受注後に商談所有者以外商談を編集させない設定


Salesforceで商談受注後に商談所有者以外商談を編集させない設定は商談オブジェクトに入力規則を作成することで可能です

以下のような入力規則を作成します

前提：
フェーズの商談受注は「Closed Won」
商談受注までは所有者以外のユーザも変更可能
商談受注後は商談所有者のみ商談レコードの編集が可能


「商談オブジェクト入力規則」
AND(
$User.Id <> OwnerId ,
ISPICKVAL(PRIORVALUE(StageName),"Closed Won") )
Capistrano 入門～タスクの実行順序を理解する～

# はじめに

デプロイに Capistrano が使用されているWebアプリケーションの開発に参加した際に、Webアプリケーションの CI 上でデプロイが行われており、以下の画像のように様々なタスクが順番に実行されているログはわかったのですが、それがどこに定義されているかわからりませんでした...

![](https://capistranorb.com/assets/images/airbrussh-screenshot.png)
※ 画像は [Capistrano 公式ドキュメント](https://capistranorb.com/documentation/overview/what-is-capistrano/) から引用

それからドキュメントやコードを読んでいくうちに、Capistrano がどのようにタスクの順序を制御しているのか少しづつ理解できるようになったので、本記事にタスクの実行順序についてまとめてみました！

# Capistrano の基本

Capistrano は Ruby で書かれたリモートサーバーへのデプロイを自動化するためのツールです。

https://capistranorb.com/

コマンド `cap xxxx deploy` (例: `cap product deploy`  や `cap staging deploy` など環境に応じて変える) を実行することでデプロイが行われます。具体的には、以下の `deploy:xxxx` という名前のタスクが以下の順番に実行されていきます。

```
deploy:starting    - start a deployment, make sure everything is ready
deploy:started     - started hook (for custom tasks)
deploy:updating    - update server(s) with a new release
deploy:updated     - updated hook
deploy:publishing  - publish the new release
deploy:published   - published hook
deploy:finishing   - finish the deployment, clean up everything
deploy:finished    - finished hook
```

上記のフローを基準として、実行したい内容に応じてデプロイのフローをカスタマイズしていきます。

# 既存のライブラリを使用して、デプロイのフローをカスタマイズする

デプロイフローのカスタマイズ方法の一つは、既存のライブラリを使った方法です。

インストールしたライブラリを `Capfile` という名前のファイルに以下のように `require` することで、ライブラリに応じたタスクがデプロイのフローに追加されます。

```rb
require 'capistrano/xxxxxxx'
```

例として、デプロイのフローに bundler のタスクの追加する `capistrano/bundler` を紹介します。

https://github.com/capistrano/bundler

このライブラリは `bundler` 関連のタスクが用意されており、デプロイ時に `bundle install` を行いたい場合等で使用します。

`Capfile` に `require 'capistrano/bundler'` を記述することで、デプロイのフローに `bundler` のタスクが組み込まれます。
具体的には、`lib/capistrano/tasks/hooks.cap` に以下のように書かれている通り、`deploy:updated` の前に `bundler:install` タスクを追加しています。

https://github.com/capistrano/bundler/blob/master/lib/capistrano/tasks/hooks.cap

```rb:capistrano/tasks/hooks.cap
before 'deploy:updated', 'bundler:install'
before 'deploy:reverted', 'bundler:install'
```

このように、ライブラリがどんなタスクを提供しており、どのタスクの前後に実行されるのか理解すれば、そのライブラリを使いこなせるようになると思います！！

# 自分でタスクを作成して、デプロイのフローをカスタマイズする

ライブラリを Capfile で require する方法以外にも、自分でタスクを作成し、それをデプロイフローに組み込むことも可能です。
自分で作成するタスクは、Rakeタスク形式で記述します。そして、`before` や `after` で既存のタスクを指定することで、好みのタイミングで自分の作成したタスクを実行することができます。

```rb
# call an existing task
before :starting, :ensure_user

after :finishing, :notify


# or define in block
namespace :deploy do
  before :starting, :ensure_user do
    #
  end

  after :finishing, :notify do
    #
  end
end
```

詳しくは以下のドキュメントに記載されています。

https://capistranorb.com/documentation/getting-started/before-after/

# おわりに

本記事で紹介した2つの方法を元に、Capistrano のタスクを読み解いていくことでデプロイのフローを理解することができるようになると思います！

僕はまだまだ Capistrano 初心者なので、足りない点や間違っていることなどもあるかもしれませんが、コメントや編集リクエスト等を送っていただけると助かります！！

# 参考にしたサイト等

- Capistrano 公式ドキュメント
    - https://capistranorb.com/
- Capistrano GitHub
    - https://github.com/capistrano/capistrano
- Qiitaの記事
    - https://qiita.com/yuku_t/items/01c0ec4389db143e27f5
    - https://qiita.com/yuku_t/items/78f32d6e5d21aee4e745
    - などなど
Docker上でWiFi確認をするのに手こずった話

## はじめに
今回はアプリ開発をしている時にめちゃくちゃ悩まされた話。
解決までを順を追って解説していきます。
結論だけほしいわ！！という人は最後だけ見に行ってください。
どう解決したんだろうかと過程を知りたい人はこのまま読み進めてください。

## 問題点
**「Docker 上に載っているアプリケーションがあります。Docker 内部から Docker を置いているPCのWiFiの接続状態を確認したいです。」**
以上のような課題があり、解決するのに試行錯誤しました。


## 解決まで
解決までの流れを順番に書いていきます。
### 1.  問題に対してアバウトな解決案を考えて、ググる

##### <font color="DeepPink">『Dockerという家に引きこもっているアプリ君。どうにかして、外からWiFi君か似たような奴を家に連れ込みたい』</font>

考えてみたものの私が最初に思ったことは『**むっず！！**』でしたが、とりあえず「**Docker Wifi 確認**」ググってみる。

##### **<font color="DeepPink">Docker コンテナ・ネットワークの理解</font>**？？＞＞＞＞**違う！！**

と陥ったわけです。


### 2. 問題解決方法の別の案を考える
 この工程に行くまでに長いことかかってしまったのですが、上で考えたことを下記のように変換してみました。

##### <font color="DeepPink">『アプリ君とDockerの家をWiFi君に会えるところまでお引越しして確認すればいい』</font>
**なんだかいけるような気がしてきた！！**
<font color="DeepPink">公式ドキュメント</font>とにらめっこして、起動時にネットワークの場所を指定できると。。これだ！！ということで解決に至りました。

## 解決した内容
**--netオプション**を使って**host**を指定してあげる。ダダこれだけのためになかなか悩まされました。
例でいうと以下のように「--net=host」すればよいらしいです。
```
docker run -d --name=web1 --net=host vaibhavthakur/docker:webinstance1
```

余談ですが、別の方法でローカルホストを追加するという方法もあるようなので、その方法でも出来そうですね。一つ解決案が見えると別の解決方法が案外見えるのが意外ですね(-.-)

## まとめ
固定概念を持たず、柔軟に考えることと公式ドキュメントを読むことの大切さを理解しました。これを機会に公式ドキュメントを読んで要約するのもありかと思えたので気が向いたらそんなこともやろうかと思います。
CurrentUserと紐づいたデータを表示する方法

【前提】
・データはUserとTodoがある。
・UserとTodoは紐づいている（User：Todo = 一：多）

【目標】
・Userの1人でログインしているときにCurrentUserに紐づいたTodoだけを表示したい。
（例　AでログインしているときはAが紐づいているTodoだけを表示）

【方法】
・text等の表示するエレメントを設置。
・InsertDynamicDataからSearchforを選択し表示したいデータを選択
※SearchforでUser=CurrentUserにするのを忘れない！！
DISPLAYなし環境でpyqt5を使おうとするとエラー（`qt.qpa.xcb: could not connect to display  qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.`）の解決策

DISPLAYなし環境でpyqt5を使おうとするとエラー（`qt.qpa.xcb: could not connect to display  qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.`）

```
$ python start.py 
qt.qpa.xcb: could not connect to display 
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.
```

以下を参考に環境変数を設定（`export QT_QPA_PLATFORM=offscreen`）することでDISPLAYなし環境でエラー回避できた

> https://stackoverflow.com/questions/37662616/create-a-pyqt-build-in-gitlab/55442821#55442821
> But QT_QPA_PLATFORM: "offscreen" work like a charm and saved the day.

```
$ export QT_QPA_PLATFORM=offscreen
$ python start.py 
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-ubuntu'
This plugin does not support propagateSizeHints()
This plugin does not support propagateSizeHints()
=================================================>
以降、動作する
```

# 参考

https://teratail.com/questions/105652

https://stackoverflow.com/questions/37662616/create-a-pyqt-build-in-gitlab/55442821#55442821
> But QT_QPA_PLATFORM: "offscreen" work like a charm and saved the day.
Salesforce Flow > Customize How Records Get Approved with Approvals

[Trailhead関係　個別の課題別 に戻る](https://qiita.com/Keiji_otsubo/items/56eb7a90bb72138ece1f)


[Customize How Records Get Approved with Approvals](https://trailhead.salesforce.com/en/content/learn/modules/business_process_automation/approvals)


毎回何が回避策なのかが理解できないエラーです。私自身はかなり前に終了していますが、全く記憶にない。ということはすんなり終わったはずですがねぇ。

# We submitted an account approval request that meets the entry criteria. We expected the request to be approved, but it was rejected. Make sure your entry criteria are Account: Type equal to 'Prospect' and Account: Employees is greater than '500'.

+ [Does anyone know how to fix this error ??](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000IPqhB)

:::note
I found that when I first created a new approval I selected the wrong object. Theres a drop down to select Account object at the very start of the process. It's not something you can change later on. What I did was change the Label Name and deactivate the approval and started a new one. 

新しい承認を最初に作成したときに、間違ったオブジェクトを選択したことがわかりました。プロセスの最初に、アカウントオブジェクトを選択するためのドロップダウンがあります。後で変更できるものではありません。私がしたことは、ラベル名を変更し、承認を無効にして、新しい承認を開始することでした。
:::

+ [Receiving message that criteria are incorrect.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PeyxASAR)
+ [I keep getting the following error message and have checked everything and it's all correct but this won't go away, any ideas ?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Pf5QW)
+ [Problem in "Build an Approval Process" Entry Criteria not met](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T2Lft)

+ ["Build an approval process" Error message with entry criteria](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bLD1Z)

:::note
All done, I used a new playground but also made sure to check that the record was submitted as I didn't do this previously. 
:::

# 未解決

+ [We submitted an account approval request that meets the entry criteria. We expected the request to be approved, but it was rejected. Make sure your entry criteria are Account: Type equal to 'Prospect' and Account: Employees is greater than '500'.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000IPqhB)

+ [ the Create an approval process using either the Jump Start or Standard Wizard the is inactive so unable to proceed further.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V000077ktYY)
cscの作法 その230

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
reverse shellのserverを実装せよ。

# 方針

- アドレス127.0.0.1 ポート5300を使う。
- 接続を待つ
- 一行、打ったら送信、受信

# サンプルコード

```
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

class Server {
	public static void Main() {
		TcpListener server = null;
		try
		{
			Int32 port = 5300;
			IPAddress localAddr = IPAddress.Parse("127.0.0.1");
			server = new TcpListener(localAddr, port);
			server.Start();
			Console.WriteLine("listen:");
			TcpClient client = server.AcceptTcpClient();
			Console.WriteLine("connect:");
			NetworkStream stream = client.GetStream();
			Byte[] bytes = new Byte[256];
			int i;
			string line;
			while ((line = Console.ReadLine()) != "bay")
			{
				Console.WriteLine(line);
				byte[] sendBytes = Encoding.UTF8.GetBytes(line + '\n');
				stream.Write(sendBytes, 0, sendBytes.Length);
				while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
				{
					 String data = System.Text.Encoding.UTF8.GetString(bytes, 0, i);
					 Console.Write(data);
				}
			}
			client.Close();
		}
		catch(SocketException e)
		{
			Console.WriteLine(e.Message);
		}
		finally
		{
			server.Stop();
		}
	}
}

```


以上。
cscの作法 その229

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
wgetを実装せよ。

# サンプルコード

```
using System.Collections;
using System.IO;
using System;
using System.Text;
using System.Net;

namespace app
{
	class test0 {
		static void Main(string[] args) {
			if (args.Length == 0)
			{
				Console.WriteLine("wget url");
				return;
			}
			ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
			WebClient wc = new WebClient();
			var filename = args[0].Split('/');
			wc.DownloadFile(args[0], filename[filename.Length - 1]);
			Console.WriteLine(filename[filename.Length - 1]);
		}
	}
}
```

# 実行結果

```
>wget https://help.qiita.com/images/qiita-brand-color.png
qiita-brand-color.png

```


以上。
バッチファイルチェック

すいません、メモ用です。
前提条件： 当処理が関数内に定義されていること。

  local file_size=
  
  
  if [ -f ${FILE_DIR}${1} ]; then
  
    RTN_CD=60
    Abort $RTN_CD "連携ファイルが存在しています。[${FILE_DIR}${1}] 異常終了"
  fi
  
  if [ -f ${FILE_DIR}${1}.SIN ]; then
  
    file_size=`stat -c %s  ${FILE_DIR}${1}.SIN`
    if  [ $file_size -gt 0 ]; then
    
      RTN_CD=70
      Abort $RTN_CD "SINファイルがセットされています。[${FILE_DIR}${1}.SIN] 異常終了"
    fi
  fi

# OPTARG使い方

  while getopts "h:p:g:d:U:W:u:f:c:o:v:I:T:tDn:" OPT
  do
      case "${OPT}" in
          h) HOST="$OPTARG";;
          p) PORT="$OPTARG";;
          g) GSC="$OPTARG";;
          d) UDB="$OPTARG";;
          U) USER="$OPTARG";;
          W) PASS="$OPTARG";;
          u) URL="$OPTARG";;
          f) FILE="$OPTARG";;
          D) DEBUG="-DForestLog=2";;
          t) COLUMN="-tColumn=true";;
          o) OUTPUTFILE="$OPTARG";;
          v) BINDVARIABLE="$OPTARG";;
          I) LOADFILE="${OPTARG}";;
          T) LOADTABLE="$OPTARG";;
          c) QUERY="$OPTARG";;
          n) NULLSTR="$OPTARG";;
          # FIXME オプション以外の引数の扱い
          -*|*) echo ">>>$OPTARG<<<>>>$@<<<" >&2
              break;;
        esac
    done


#引数がNのメソッド

    public static Number sum(Object...objects) {
    	return GeneratedAppUtils.sum(objects);
    }

エクセル万能関数（項目の連番をカウントする）
=COUNT(cell:INDIRECT(ADDRESS(ROW()-1,1)))+1

-- ロール権限を持ったユーザを作成する。 
CREATE ROLE user_s
-- ユーザにログイン機能を与える
ALTER ROLE user_s LOGIN
-- ユーザパスワードを設定する。
ALTER ROLE user_s PASSWORD 'pass'
-- 権限を付与する。
GRANT SELECT ON table_s TO user

## データベースクラスタを新規作成する。
initdb --encoding=UTF-8

## powershell 空フォルダ自動生成
for($i=6; $i -le 14; $i++) {
$N = "{0:000}" -f $i
$N2 = "CC" + $N
mkdir $N2
}

##b
--function定義（int→varchar）
CREATE OR REPLACE FUNCTION public.int4varchar(integer)
 RETURNS character varying
 LANGUAGE sql
 IMMUTABLE STRICT
AS $function$SELECT textin(int4out($1)) AS varchar$function$;

--cast定義（int→varchar）
create cast (int4 as varchar) with function int4varchar(integer) as implicit;

--function定義（varchar→int）
CREATE OR REPLACE FUNCTION public.varcharint4(character varying)
 RETURNS integer
 LANGUAGE sql
 IMMUTABLE STRICT
AS $function$SELECT int4in(varcharout($1)) AS varchar$function$;

--cast定義（varchar→int）
create cast (varchar as int4) with function varcharint4(character varying) as implicit;


--確認用（int→varcharとvarchar→intの2レコードが抽出されればOK）
select pg_cast.*, t1.typname, t2.typname
from pg_cast
left join pg_type t1
  on t1.oid = pg_cast.castsource
left join pg_type t2
  on t2.oid = pg_cast.casttarget
where
(
	castsource = 'int4'::regtype
	and casttarget ='varchar'::regtype
)
or
(
	castsource = 'varchar'::regtype
	and casttarget = 'int4'::regtype
)
go言語　 time.Format()  time.Round()　の挙動に注意

# まとめ
- `time.Round(time.Second)`を使うと、時刻は四捨五入的に処理される（真ん中で切り分ける）
- `time.Format("2006-01-02 15:04:05")`を使うと、秒未満は切り捨てられる

# 場面
SQLiteを使っていて、秒単位の時刻を記録していた。その際に想定外の値のズレが発生したため、調査していた。上記の仕様を確認した。

# コード
```golang
	a := time.Date(2000, 1, 1, 1, 1, 1, 300_000_000, time.UTC)
	b := time.Date(2000, 1, 1, 1, 1, 1, 700_000_000, time.UTC)

	fmt.Printf("round a %v\n", a.Round(time.Second))//round a 2000-01-01 01:01:01 +0000 UTC
	fmt.Printf("round b %v\n", b.Round(time.Second))//round b 2000-01-01 01:01:02 +0000 UTC

	fmt.Printf("format a %v\n", a.Format("2006-01-02 15:04:05")) //format a 2000-01-01 01:01:01
	fmt.Printf("format b %v\n", b.Format("2006-01-02 15:04:05")) //format b 2000-01-01 01:01:01

```
WORDCLOUDをVIS.JSにマッピング

https://qiita.com/EasyCording/items/97df01e74679c28853f3

前回は上記の挑戦をやってみた。
しかしながらCYTOSCAPE.jsにはどうしても解決できない問題があった

EDGE長さを数値で指定できない
・レイアウトCOSE　→　×
・レイアウトCOLA　→　どうもうまくいかない

結果的にであるが、CYTOSCAPE.JSはやめることにして、VIS.JSに取り組んでいる。

ただしVIS.JSには、課題があって、NODEにSVGをマッピングすることができない。
（正確に言うと、REACT-COMPONENTの使い方が分からない・・・というのが正直なところ）

# cytoscape.jsの場合

以下のように、COMPONENTに```cy={(cy) => { myCyRef = cy; }```を足すことで
DOMを直接触って参照できる。


```sample.js
let myCyRef = null;

constructor(props) {
    super(props);
    this.state = {
      elements: {},
    }
  }

  componentDidMount() {
    const Cross = fetchCrossvalidData();
    this.setState({ elements: Cross });
  }

componentDidUpdate() {
    this.loadSVG();
    }

loadSVG() {
    this.state.elements.map((value, index, array) => {
      const params = { // some querying code was written here  // }
      const query = new URLSearchParams(params);
      fetch(
        apiurl+'/svg?'+query.toString()
      )
        .then(r => r.text())
        .then(data => {
          if(data.indexOf('<svg')>0)  //get some svg data
          {
          data=data.replaceAll('\\',"").slice(1).slice(0,-1);
          myCyRef.filter("node[id='" + value['data'].id + "']").css("background-image", "data:image/svg+xml;utf8," + encodeURIComponent(data));
          }
        }).catch(err => {
          console.log(err);
        });
    });
  }
render() {
    if (this.state.elements.length > 0 && this.state.crossvalid.length > 0) {
      
      return (
        <CytoscapeComponent cy={(cy) => { myCyRef = cy; }}
          stylesheet={styles}
          elements={this.state.elements}
          style={{ minWidth: "800", minHeight: "800px" }}
          layout={layout}
        />
      );
    } else {
      return <div className="App">
        Loading...Patent Data</div>
    }
  }
```

# vis.jsの場合

出来ると言えばできるのであるが、REACTのコンポーネントになっていない。
HOOKを使えば出来るのかもしれないが、ソースが無いとコピペできない。

いまここでREACTの勉強中です。
（誰がCOMPONENTの作り方教えてください）

```sample.js
    var nodes = new vis.DataSet([
      { id: 1, shape: "circularImage", image: "dummy.png" },
      { id: 2, shape: "circularImage", image: "dummy.png" },
    ]);

    network = new vis.Network(container, data, options);

    network.on("click", function(properties) {
          nodes.update({ id: properties.nodes[0], image: 'image.svg' });
        });
    });
```


![mountain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212914/2e0d4fb9-cb52-e681-5475-a5f6140fca06.png)
![man.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212914/5eb1385a-d4dc-ee8e-2ab9-03e9f7bb89ca.png)
![woman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212914/80cd269f-1589-5ee6-e62d-366f66701b72.png)
個人情報保護法関連情報

### [全体の目次](https://qiita.com/tetz1/items/da4eb31b920f2acf4349)
---

### [個人情報保護委員会ウェブサイト](https://www.ppc.go.jp/index.html)

- [個人情報保護委員会ウェブサイト - 個人情報保護法等](https://www.ppc.go.jp/personalinfo/)

- [個人情報保護委員会ウェブサイト - 法令・ガイドライン等](https://www.ppc.go.jp/personalinfo/legal/)

- [個人情報の保護に関する法律についてのガイドライン（通則編）](https://www.ppc.go.jp/personalinfo/legal/guidelines_tsusoku/)

- [個人情報の保護に関する法律についてのガイドライン（外国にある第三者への提供編）](https://www.ppc.go.jp/personalinfo/legal/guidelines_offshore/)

- [個人情報の保護に関する法律についてのガイドライン（第三者提供時の確認・記録義務編）](https://www.ppc.go.jp/personalinfo/legal/guidelines_thirdparty/)


- [個人情報の保護に関する法律についてのガイドライン（仮名加工情報・匿名加工情報編）](https://www.ppc.go.jp/personalinfo/legal/guidelines_anonymous/)

- [個人情報の保護に関する法律についてのガイドライン（認定個人情報保護団体編）](https://www.ppc.go.jp/personalinfo/legal/guidelines_ninteidantai/)

- [「個人情報の保護に関する法律についてのガイドライン」に関するQ&A](https://www.ppc.go.jp/personalinfo/faq/APPI_QA/)