OmniAICreator/Qiita-1.07M huggingface dataset:
Python3 csv.DictReaderをforするときは一度辞書で受ける

# `csv.DictReader`を`for`するときは一度辞書で受ける

`csv.DictReader`をそのまま`for`すると見出しだけ列挙されます。これは一度辞書として受けることで解決できます。原因は`csv.DictReader`の`iter`結果が`dict`であること、`dict`の`for`がキーを返すことです。`csv.DictReader`ではキーが見出しに対応します。アンパックしたくなりますが、`dict`の場合は遠回りが近道です。

```py:dictのキーだけ列挙されるコード
dd = ({"A":1, "B":2, "C":3},
      {"A":4, "B":5, "C":6})
for a, b, c in dd:
    print((a, b, c))
#('A', 'B', 'C')
#('A', 'B', 'C')
```

```py:dictを取得できるコード
dd = ({"A":1, "B":2, "C":3},
      {"A":4, "B":5, "C":6})
for d in dd:
    print(d)
#{'A': 1, 'B': 2, 'C': 3}
#{'A': 4, 'B': 5, 'C': 6}
```

```py:csv.DictReaderの見出しが列挙されるコード
import csv

csv_raw = "A, B, C\n1,2,3\n4,5,6".split("\n")
for a, b, c in csv.DictReader(csv_raw):
    print((a, b, c))
#('A', ' B', ' C')
#('A', ' B', ' C')
```

```py:csv.DictReaderの行（dict）を取得できるコード
import csv

csv_raw = "A, B, C\n1,2,3\n4,5,6".split("\n")
for d in csv.DictReader(csv_raw):
    print(d)
#{'A': '1', ' B': '2', ' C': '3'}
#{'A': '4', ' B': '5', ' C': '6'}
```

# 参考

- [dict - Python 3 Documentation](https://docs.python.org/ja/3/library/stdtypes.html#dict)
- [5.3. タプルとシーケンス - Python 3 Documentation（末尾にアンパックの解説）](https://docs.python.org/ja/3/tutorial/datastructures.html#tuples-and-sequences)
Symfony4.1アップグレードから、長く使えるコードについて考えてみた

タイトル詐欺かも。
「サービスを自作クラスでラップして使ってたので助かった」話ですね。

要点は：

- Symfony 4.1を5.4に更新。
  - いわゆるUpgradeは全て失敗したので、5.4をクリーンインストールして、そこにコードをコピペして動かした。
  - 作業は思ったより簡単にできた。
  - クラス名やネームスペースが変わったぐらいで、文字列変換で対応できた。
- ただし、フレームワーク側での大きな変更点は２つあった。
  - `Swiftmailer`が廃止され、`Symfony/Mailer`が採用されてた。
  - `Twig`にnamespaceが導入されてた。
- たまたま`Mailer`も`Twig`も別クラスでラップしてたので、修正が一か所ですんだ。
  - ラッキーだったね。

という話です。


## Twig

`twig`は、簡単なクラスでラップしてましたので、`\Twig_Environment`を`\Twig\Environment`に書き換えるだけで対応が完了！
コードは、こんな感じ。

```php
 class Template
{
    private \Twig\Environment $twig;
    public function __construct(\Twig\Environment $twig)
    {
        $this->twig = $twig;
    }
    public function render($view, $parameters = []): string
    {
        return $this->twig->render($view, $parameters);
    }
}
```

そもそも、なぜラップする気になったのか不思議なぐらい単純なクラス。これならクラスを挟まなくても文字列置換で十分対応できたでしょう。
おそらく名前空間のないクラス、`Twig_Environment`を直接使いたくなかったとかでしょう…

## SwiftMailerが`Symfony/Mailer`に

メーラーをラップするのは難しいので、逆にメールの情報を共通化して
利用してました。ので、結果的に修正が一か所で済みました。

### Abstract Class

最初からアブストラクトクラスを作ってたので、こんな風に改良。

```php
abstract class AbstractMailer
{
    protected MailerInterface $mailer;
    protected Template $template;
    public function __construct(MailerInterface $mailer, Template $template)
    {
        $this->mailer = $mailer;
        $this->template = $template;
    }
    abstract public function render(): string;
    abstract public function subject(): string;
    abstract public function from(): string;
    abstract public function mailTo(): string;
    public function mail(): void
    {
        $mail = new Email();
        $mail->from($this->from())
            ->to($this->mailTo())
            ->subject($this->subject())
            ->html($this->render());
        $this->mailer->send($mail);
    }
}
```

### 使い方

使う場合は、次のようなクラスとして実装します。

```php
class WelcomeUserMailer extends AbstractMailer
{
    private User $user;
    public function subject(): string {
        return 'Welcome!';
    }
    public function mailTo(): string {
        return $this->user->getEmail();
    }
    public function from(): string {
        return 'from@example.com';
    }
    public function setUser(User $user)
    {
        $this->user = $user;
    }
    public function render(): string
    {
        return $this->twig->render('welcome.twig', ['user' => $this->user]);
    }
}
```

`WelcomeUserMailer`はDIしてもらっておいて、

```php
$this->mailer->setUser($user);
$this->mailer->mail();
```

となって、Controller側の修正箇所はなしでした。

## まとめ

話としては以上なのだけど、無理やりまとめると、

- 外部ライブラリは不安定。
- 守りたいのはコントローラーも含んだ自分の書いたコード。
- ラップするレイヤーも、自分のコードとして管理するほうが良さそう。
- でも、メールやORMのように複雑なAPIがある場合に、レイヤーを挟むのは難しい…
  - メールだと、メールという情報を統一化したらうまくできた。

やはり一度書いたコードは、出来るだけ長く使いたいですね。
小ワザ集：Libertyでガーベッジ・コレクションの詳細情報を取得する

この記事は，以前IBMのdeveloperWorks上で公開されていたWAS Traditional環境向けの[WAS小ワザ集](https://community.ibm.com/community/user/wasdevops/blogs/takakiyo-tanaka1/2022/02/12/was-kowaza?CommunityKey=d6c93aa2-6e10-48da-96dc-3831da8ee185&tab=recentcommunityblogsdashboard)のLiberty版です。

# ガーベッジ・コレクション(GC)の記録

Javaヒープの枯渇によるOutOfMemoryErrorや，GCによるパフォーマンスの問題を調査する際には，Javaヒープの使用状況とGCの実行を記録することが必須です。Libertyを使用する際には，できるだけGCの情報を記録するようにしましょう。

GCの情報を記録するためには，JVMの起動オプションを指定します。Libertyでは，サーバーの構成ファイルであるserver.xmlと同じディレクトリにjvm.optionsというファイルを作成し，その中に起動オプションを指定します。オプションは，1行に一つずつ指定するようにします。指定する内容は，使用しているJVMの種類によって異なります。

# J9VM/OpenJ9での記録
製品の導入ディスクに含まれている[IBM SDK for Java Version 8.x](https://www.ibm.com/docs/ja/sdk-java-technology/8?topic=SSYKE2_8.0.0/welcome/welcome_javasdk_version.html)や，[IBM Semeru Runtimes](https://developer.ibm.com/languages/java/semeru-runtimes/)を使用している場合です。これらの環境では，IBMが独自に開発したJ9VMや，それをOSSとして公開した[OpenJ9](https://www.eclipse.org/openj9/docs/)が使用されています。
jvm.optionsに以下の内容を記述します。この設定では，GCの記録は他のJVM出力と分けられて，messages.logなどと同じディレクトリにファイルとして記録されます。ファイル名はverbosegcからはじまり，日付やプロセスIDなどがふくまれたものになります。

```shell:jvm.options
-verbose:gc
-Xverbosegclog:logs/verbosegc.%Y%m%d.%H%M%S.%pid.log
```

# HotSpot VMでの記録
[Eclipse Temurin](https://projects.eclipse.org/projects/adoptium.temurin)や他のHotSpot VM系のJDKディストリビューションを使用している場合には，使用しているJavaのバージョンによって設定内容が異なります。

Java 11/17や，それ以降のバージョンを使用している場合には，以下の内容を記述します。同じくlogsディレクトリにverbosegc.logというファイル名でGCの情報が記録されます。サーバーを再起動すると，以前の情報はファイル末尾に数字がついたファイルとしてバックアップされます。

```shell:jvm.options
-Xlog:gc*:logs/verbosegc.log:time,level,tags
```

Java 8を使用している場合には，以下の内容を記述します。この場合は，verbosegc.logの情報はサーバーを再起動するたびに上書きされてしまいます。トラブルなどがあった場合には，再起動する前にかならずlogsディレクトリのファイルをバックアップして情報を残すようにしてください。

```shell:jvm.options
-verbose:gc
-Xloggc:logs/verbosegc.log
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
```

# 余談：サーバーごとに起動するJVMを変える

今回の記事を執筆するに当たって，サーバーごとに起動するJVMをSemeruだったりTemurinだったりに変えてテストを実行しました。このように特定のサーバーを特定のJVMで起動して利用したい場合には，server.envにJAVA_HOME環境変数を記述します。

```shell
% cat usr/servers/semeru17/server.env 
JAVA_HOME=/Library/Java/JavaVirtualMachines/ibm-semeru-open-17.jdk/Contents/Home

% cat usr/servers/temurin17/server.env 
JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home

% cat usr/servers/temurin8/server.env 
JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home
```

ただし，このような環境に依存する絶対パスを構成ファイルに記述してしまうと，その環境から`server package`コマンドで作成したアーカイブに可搬性がなくなってしまいますのでご注意ください。
Python3 CSVをタプルやリストに読み込む

# CSVをタプルやリストに読み込む

CSVをタプルやリストに読み込むには`csv.DictReader`クラスを作成して`tuple()`、`list()`に渡します。空のリストと`for`は不要です。

```py
tuple(csv.DictReader(...)) # タプルへ変換
list(csv.DictReader(...))  # リストへ変換
```

文字列から作成したCSVをタプルへ変換する具体例は次の通りです。

```py:CSV文字列➞タプル変換
import csv
from pprint import pp

csv_raw  = "A, B, C\n1,2,3\n4,5,6\n7,8,9".split("\n")
csv_rows = tuple(csv.DictReader(csv_raw))

pp(csv_rows)
#({'A': '1', ' B': '2', ' C': '3'},
# {'A': '4', ' B': '5', ' C': '6'},
# {'A': '7', ' B': '8', ' C': '9'})
```

:::note warn
上の出力結果が`'A': '1'`であるように値は文字列として読み込まれます。JSONなどに変換する場合は読み込み後に数値へ変換してください。
:::

# `csv.DictReader`クラスが`tuple()`や`list()`にそのまま渡せる理由

`csv.DictReader`クラスが`tuple()`や`list()`にそのまま渡せるのは`__iter__()`メソッドを実装するためです。そのため、`csv.DictReader`クラスは内包表記、`filter()`、`map()`も適用できます。

```py
import csv
from pprint import pp

csv_raw    = "A, B, C\n1,2,3\n4,5,6\n7,8,9".split("\n")
csv_reader = csv.DictReader(csv_raw)
pp(tuple(d for d in csv_reader if int(d["A"]) % 2 == 0))
# ({'A': '4', ' B': '5', ' C': '6'},)
```

# 参考

- [csv.DictReaderクラス - Python 3 Documentation](https://docs.python.org/ja/3/library/csv.html#csv.DictReader)
- [tupleクラス - Python 3 Documentation](https://docs.python.org/ja/3/library/stdtypes.html#tuple)
- [listクラス - Python 3 Documentation](https://docs.python.org/ja/3/library/stdtypes.html#list)
jsonpとは

corsを回避するためにscriptタグを用いてajaxのようなことを実現する技術。

ブラウザ上でクロスドメインな通信には制限があり、いくつか制限をすり抜ける方法があり、それがJSONP

ただ、CORSの方が細かい制御ができて安全なのでそちらを使ったほうが良い
ネットワークのお勉強：SDN 

# SDN (Software Defined Networking)についてまとめ
## SDNとは
仮想的なネットワークの構築技術の１つ
・仲間
VPN
VLAN
## 何が違う？
・VLAN
VLANはL2レベルの仮想化技術
物理的な1つのネットワークをタグ付け（タグVLAN）等により
仮想的に分割された複数のネットワークとして取り扱う。

・VPN
VPNは専用線の仮想化技術
VPNトンネルを作成し、トンネル内を専用線の代替として扱う。

・SDN
SDNはネットワークそのものの仮想化技術
ソフトウェアによって仮想化されたネットワークを作り出し、ネットワークを総合的に
管理することで大きな変更も簡単に行うことができる。
## 具体的にどうやるの？
・OpenFlow（SDN標準プロトコル）を使う
全ネットワーク機器をOpenFlow対応のもので揃える...★敷居が高い
SDNコントローラーサーバを立てる
SDNコントローラーの設定に従って対応機器内に仮想的に独立したセキュアなネットワークが構築される。
Java Silver SE11 8章

# Java Silver SE11 8章
[黒本](https://www.amazon.co.jp/gp/product/4295007625/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)をもとに学んだことをアウトプットしていきます。
主に問題を解いていて、間違えた箇所もしくは知らなかった内容になります。

## 関数型インタフェース
実装が必要なメソッドを１つだけ持つインタフェースのこと。
抽象メソッドを１つだけ持つので、後に記述するラムダ式が「どのメソッドを実装するのか」必然的に決めることができる。
`@FunctionalInterface`アノテーションを付与することで、明示することも可能。

## ラムダ式
簡単なインタフェースでも新しくクラスを作成する必要がある。
この問題を新しくクラスを作る代わりに、ラムダ式に置き換えることができる。

### ルール
* 関数型インタフェースを使う
* 実行したい処理が１つのみの場合は、「()」「{}」も省略可能
  * また省略した場合、戻り値を戻すにはreturnを記述できない
* メソッド内のローカル変数と同じ名前の変数を、ラムダ式内で宣言できない
* 実施的なfinalな変数でなければ、ラムダ式内から外の変数ヘはアクセスできない
  * ラムダ式は宣言されたタイミングで使用されるわけではないので、宣言後に変数を変更されると意図しない動作をする可能性がある

```java:構文
関数型インタフェースの型 変数名 = (引数) -> {処理};
```

```java:例1
public class Main {
	public static void main(String[] args) {

		// {}がある場合は、returnは省略できない
		Function f = (name) -> {
			return "hello" + name;
		};
		// 処理が１つかつ{}がない場合は、returnを記述できない
		Function f2 = (name) ->  "hello " + name;

 		System.out.println(f.test("Lambda")); // hello Lambda
 		System.out.println(f2.test("Lambda2")); // hello Lambda2
	}

	private static interface Function {
		String test(String name);
	}
}
```
```java:例２
public class Main {
	public static void main(String[] args) {
		String str = "A";
		Function f = (val) -> {
			System.out.println(val);
		};
		f.test(str); // A
		f.test("B"); // B

		// コンパイルエラー
//		Function f2 = (str) -> {
//			System.out.println(str);
//		};
	}
}
interface Function{
	void test(String val);
}
```
```Function f2 = (str) -> {```は、```String str = "A";```を再定義しようとしている

```java:例３
public class Main {
	public static void main(String[] args) {
		int cnt = 0;
		Runnable r = () -> {
			for (cnt = 0; cnt < 10; cnt++) {
				System.out.println(cnt++);
			}
		};
		new Thread(r).start(); // コンパイルエラー
	}
}
```
ラムダ式内で10回処理するだけなら、```for (int cnt = 0; cnt < 10; cnt++) {```と変更することで「02468」と表示させることができる。


## java.util.functionパッケージ
頻繁に使われる関数型インタフェースは、java.util.functionパッケージに記述されている。
例：`Consumer`「消費者」, `Supplier`「供給者」, `Predicate`「断定」, `Function`「処理」 など

| 関数型インタフェース  | メソッド          | 内容 |
|:-----------------|:---------------|:----|
| Consumer\<T>     | void accept(T) | 引数を受け取り、処理を実行(戻り値なし)    |
| Supplier\<T>     | T get()        | 引数を受け取らず、戻り値を返す  |
| Predicate\<T>    | boolean test(T) | 引数を受け取り、判定を返す  |
| Function\<T, R>  | R apply(R)     | 引数を受け取り、戻り値(R)を返す  |
awswranglerにて pyarrow.lib.ArrowTypeError: Did not pass numpy.dtype object のエラー

最近、業務でデータ基盤の構築をしており、その中でETL処置のために`awswrangler`というライブラリを使用することがあります。
これを使うと`S3 <-> pandas.DataFrame`などのやりとりが非常に簡単に行えて便利です。

ただ、そのセットアップで表題のエラーが出ることがあったので簡潔にまとめておきます。

# 何が起きたか？
以下のようにpandasのDataFrameをawswanglerでS3にputしようとした際にエラーが発生しました。

```python
import awswrangler as wr

path = "s3://hoge_bucket/hoge.parquet"
wr.s3.to_parquet(
	df=df,
	path=path,
)
```
型の問題なことはエラーからわかりますが、`df`のtypeを調べてみても間違いなく`<class 'pandas.core.frame.DataFrame'>`でした。

# 原因
どうやらライブラリのバージョンの問題のようです。

https://github.com/Azure/MachineLearningNotebooks/issues/1314

- awswanglerが依存している`pyarrow`が3系なら解決済み
- pyarrowが2系かつnumpyが`1.20.x`のだと起きる

# どう解決したか？
上記から、以下どちらかが必要です。
- pyarrowを`3.0.0`にアップグレード
- numpyを`<1.20.0`よりしたのバージョンにダウングレード

僕が業務でawswanglerを使用しようとしていたのは`AWS MWAA`においてだったため、numpyをダウングレードして解決しました。
※ ↓ いくつかのサービスではpyarrowが2系でないと使用できない、、、

>⚠️ For platforms without PyArrow 3 support (e.g. EMR, Glue PySpark Job, MWAA):
➡️pip install pyarrow==2 awswrangler

https://github.com/awslabs/aws-data-wrangler
なぜプログラミングスキルが向上したのか考えてみた

以前努めていた会社の上司から連絡がありました。その内容は以下のようなものでした。

「なぜ、同期の中で君だけ飛び抜けて成長したのか？他の子と同じ環境にいたはずなのに。」

正直なところ、自分がずば抜けて成長したという認識はなく、自分では今でもダメだと思っているので、そのように言われたことに大変驚きました。
しかしながら、自分が成長できていたと仮定して、自分がどうプログラミングスキルを磨いてきたのか振り返るよい機会になったので皆さんと共有したいと思います。

これからプログラミングを学ぼうとしている方々の参考になれば幸いです。

#自己紹介
都内のIT企業でプログラマーとして勤務している38歳。大学卒業後、未経験から組み込みエンジニアになり、数年前にフィールドをIT企業に移してAWS上でWebアプリの開発しています。

## 取り組んだこと

- とにかくやってみる
- とにかく勉強してみる
- 人の書いたコードを読む、修正してみる
- 人の技は盗む、パクる
- パターン化する
- 素直に人に聞く
- バカでもできる方法を考える

##とにかくやってみる

自分はあまり座学は得意ではなかったのでとにかくコードを手探りで書く、からの調べる、が良かったのかな、と思いました。とある研究によると、とにかくやってみてから勉強する、というのが学習効果が高いそうです。

##とにかく勉強してみる

理解できないとが多かったのですが、一応本を読んだり調べたりしました。正直、どこまで自分の役にたったのかよく分かっていません。しかし、一説によると現在の読書量が年収と相関関係があるらしいので、本を読んで勉強するというのは良いことかもしれません。

##人の書いたコードを読む、修正してみる

もともとプログラミング経験なしだったことから、まっさらな状態からコードは書かせてもらえませんでした。人の書いたコードを一部修正して新機能を実装する、もしくは追加する、ということをいろいろやらされました。少しでも間違えたり下手な修正をすると叱られたのですが、今思うとあの経験は今も生きています。どんなコードが修正、追加しやすいのかどうか、もとのコードを壊さずに最小の修正でやるにはどうしたらよいか、というのを体感できたのはよかったと思います。一行の追加で自分の望む動作をソフトウェアにさせる、というのを理想としていました。まぁ、実際にはかなり難しいですけどね。

##人の技は盗む、パクる

変な意地ははらずに、他の人のコードは使えると思ったらまるまるパクる。そのままパクれなければ少しの修正でパクる、それも難しそうなら概念だけでもいいからパクる。コメントですらパクる。IQ180の人が一週間かけたコードでも、パクってしまえば数秒で実装できますよね。もちろん、法律に触れることはやっては駄目ですよ！

##パターン化する

一から全部書くのは面倒くさいので、まずはパターンを探すのが重要だと思います。さすがに新規の開発でかつ不慣れな言語や開発環境で右も左も分からない状態でパターン化するのは無理ですが、ある程度プロジェクトが進めば一定のパターンが見えてくるはずです。そのような場合は必ずパターン化して横展開します。もちろん、他のプロジェクトでも使えるなら、同じようにパターンを展開します。ミスも減りますし、他の人がコード見たときにパターンがある方がコードを読みやすくなります。

##素直に人に聞く

僕は誰が相手でも必要性や興味があれば頭を下げて教えをこいます。「SPAってなんですか？教えてください！」ってな感じです。おかげで今React触ってます。毎日が入社一日目の気持ちで働いております。

##バカでもできる方法を考える

とにかく自分で考える量をいかに減らすか、というのに集中していました。頭が良い人であれば、その賢い頭を使って考えるというのが正解かもしれません。しかし、僕のように頭が良くない人間がそれをやると、すぐにメモリいっぱいになりファンがうなりだします。頭から煙がでてしまいます。よって、利用できるものはフルで利用するし、自分が気にしなくてはいけない箇所をいかに減らすか、ということが重要になります。利用できるもの、というのはフレームワーク、ライブラリ、人、考え方、やり方、金、コネ、制度、情報、なんでも全部です。「バカでもできる方法はないか？」というのを常に考えるクセがついています。ただ、人に嫌われてると協力も得にくいので、普段から周りと仲良くしておくのが僕にとっては大切でした。

#まとめ
こうやって振り返ると、テクニック的なことは意外と少なく、どう考えるか、どう取り組むか、ということを気をつけていたようですね。デザインパターンとかテクニック的なことを覚えるのもよいですが、若いうちは社会人としてどう働くか、自分なりの方法を模索して構築するのが良いかもしれませんね！

以上になりますが、あくまで僕はこうだった、というものなので、参考程度でお願いします。
個人開発しくじり先生 パチプロ支援ツールを作って15日でサービス終了した話

# 誰も使わないサービスにしないために
私が初めて作ったパンツをシェアするwebアプリは、たったユーザ数4人でサービス終了しました。([個人開発しくじり先生 ユーザ数4人でサービス終了した話](https://qiita.com/yuno_miyako/items/279944fd5ae109924c41))

その時の失敗を以下のように分析しました。

① 友人と盛り上がってその場の**思いつき**で企画してしまった
② **使われるかわからないまま**に作りたいものを作ってしまった
③ 全部の機能が完成するまで**リリースしなかった**

そこで今回は、きちんと上記の３つに対して以下の対策を立て、リーンにプロダクトを作っていきました。

① **バーニングニーズ**を見つけ、自分もしくは顧客が抱える「本当の課題」を解決することを目的にプロダクト開発を行う
② **ユーザインタビュー**をして、買ってくれる顧客が欲しいものを作るためにすり合わせを実施する
③ **MVP**(最もコアの価値がある機能を有したプロダクト)を作ったらそれでリリースしてフィードバックをもらう

# パチプロ支援ツールを作る

## ① バーニングニーズを見つけた
友人にパチンコで月数十万円を稼いで生活をしているパチプロがいたため、単純な興味からどんな風にしてパチンコで稼いでいるのか話を聞いた。
その中で大きなバーニングニーズがあることがわかった。

パチプロは主にデータサイト(パチンコ台が今日どれくらい打たれたかとか、大当たりが何回出たかなどの情報が30分間隔で更新されるサイト)を利用している。毎日夜に**1~2時間程度かけてデータサイトを巡り**、明日稼げそうな台を探している。ここに非常に手間と時間がかかっていた。
これを自動化させることで、1時間/日 × 30日 = 30時間/月の苦痛な時間を削減できる。

## ② ユーザインタビューを繰り返す
パチプロの友人とは何度もミーティングを重ね、美味しい台を見つける計算ロジック(向こうは数学的に考えているわけではなかったりするので、それを数式に落とし込むことは結構大変だった)、表示したい情報、UIのすり合わせを行った。
自分自身もパチンコを打ってみて、こういう仕組みなのかというのを実体験しながらプロダクト像を作っていった。

## ③ MVPを作ってリリース
MVPは1時間かけて回らないと収集できないデータを一瞬で集めて、集計し、翌日どこのお店のどの台を狙うべきか一覧で出ることだったので、その機能を作って2日でリリースした。
最初のMVPは、UIなどない**API**だ。
「このURLを叩くとJSONでスコアの高い台がソートされて一覧が出るから」とパチプロに伝えて使ってもらった。
お金を払ってでも使いたいほどに困っているか確かめるため、**きちんと料金をとった**。(ここをなあなあにすると、別にいらないけど付き合いで使ってあげるというのが生じてしまう)

# なぜ15日でサービス終了したのか

## スクレイピングしているのバレてアカウントを消されたため
データサイトの利用規約にスクレイピング禁止がされているのは当初から認識していたが、そこから目を逸らして実現させてしまった

# しくじりから学んだこと
一発アウトな夜も眠れぬ問題からは目を逸らさないこと。

* 利用規約をちゃんと読む
* 実現可能なのか
* ニーズがあるのか
* セキュリティの問題はないのか
* ビジネスモデルは成り立つのか
* データソースはあるのか

などなど。
あなたのプロジェクトの夜も眠れぬ問題って何ですか？
python3でLeetCode の「 Maximum Depth of Binary Tree」を理解した

# 目的
かなり備忘録。ちょっと再帰関数あたり自分の考えを無理やり文字にしたような形でわかりづらいかと思うがご了承いただきたい。
[「1389. Create Target Array in the Given Order」](https://leetcode.com/problems/create-target-array-in-the-given-order/)などのノードだとかツリーとかが出てこない問題は絶対クリアできるとまではいかないが、少なくとも解説見れば理解できた。

だが、このNodeTreeなどは何をどのように実装しているのかが全く理解できず長らくクリアできず解説も訳がわからなかった。
しかし、今ちゃんと理解できたのでこちらに記載する。


# problem
Given the root of a binary tree, return its maximum depth.

A binary tree's maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

![スクリーンショット 2022-02-13 午前11.13.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487834/05f090ba-5d6f-1554-eae7-3b977e650e1f.png)


Example 1:

```
Input: root = [3,9,20,null,null,15,7]
Output: 3
```

Example 2:

```
Input: root = [1,null,2]
Output: 2
``` 

Constraints:

```
The number of nodes in the tree is in the range [0, 104].
-100 <= Node.val <= 100
```

# 前提
問題の中の関数の引数でrootが渡されていて、exampleのrootを見るとrootはリスト??と思ったが、これが全ての間違いの始まりだった。
rootとして何を受け取っているのか中身を見てみた。

"**TREENODE IS NOT JUST A LIST!!**"

```json
TreeNode{
  // root node(depth = 1)
  val: 3, 
  // left side of the tree
  left: TreeNode{
    // depth = 1
    val: 9, 
    left: None, 
    right: None
  }, 
  // right side of the tree
  right: TreeNode{
    // depth = 2
    val: 20, 
    left: TreeNode{
      // depth = 3
      val: 15, 
      left: None, 
      right: None}, 
    right: TreeNode{
      // depth = 3
      val: 7, 
      left: None, 
      right: None}
  }
}
```

ツリーそのものがrootという引数に入っていて、listなどでは全くなかった。
solutionで出てくるroot.leftなどは上の中身を見ると想像がつきやすいと思う。

# solution
```python
class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if root:
            return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))  
        else:
            return 0
```

再帰関数で一回再帰するごとに一個深い層を見ている

1. rootは左右両方あるからreturn1
2. left1にはleft,rightがないから０が返って```self.maxDepth(root.left), self.maxDepth(root.right)```は0
3. right１層目はleft2層目もright2層目もあるから1が返る(```self.maxDepth(root.left), self.maxDepth(root.right)```は1)
4. rightの下のleft2層目はleft,rightがないから０を返す(```self.maxDepth(root.left), self.maxDepth(root.right)```は0)
5. rightの下のright2層目はleft,rightがないから０を返す(```self.maxDepth(root.left, self.maxDepth(root.right))```は0)

ちょっとわかりづらいかもしれないが、単純な再帰関数。

# まとめ

かなりスッキリしました。
もう一度実装してみたいと思う。
OPTIONSメソッドを無効にしたらプリフライトリクエストも無効にならないか

セキュリティ対策としてサーバ側でOPTIONSメソッドを有効にする場合がある。しかし、この場合プリフライトリクエストが飛ばなくなるのか気になったので調べた。

結論から言うと問題なかった

そもそもリクエストが「単純なリクエスト」であればプリフライトリクエストも飛ばないので、深く気にしなくて良い
素のvim環境を触った時にsetコマンドでサクッと見た目を整える

# 初めに
どこかのサーバにSSH接続してvimでファイル編集する場合、大抵デフォルト設定だったりします。
その際にsetコマンドを使って最低限の表示をよくする方法を紹介します。


# コマンド
コマンドモードで以下を実行するだけです。
```
set number cursorline wrap list
```

例えば、ubuntu20.04のvimでファイルを開いた時の違い、こんな感じになります。
## 適用前
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136416/f233bd95-17f2-41f3-bf47-a8cd9d17be89.png">

## 適用後
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136416/45c615ea-803a-3575-0733-ef0ed28507d9.png">

# コマンド解説
number：行番号を表示します
cursorline：カーソルの行に横線表示します
wrap：画面外の文字を折り返します
list：行末に$を表示します。

全て覚える必要はないので、長いと思ったのであれば、まずは、`set number`のみや、`set number wrap`だけでも覚えると便利かと思います。

ちなみに、解除するときは、noをつければ良いです。
例：
```
:set nonumber nocursorline nowrap nolist
```

## その他
半角スペースでタブ幅も設定したい場合も覚えると良いかもしれないです。
```
set expandtab tabstop=2
```
expandtab：タブ文字を半角スペースにします。
tabstop：半角スペースの幅を調整します。

全てを覚えた人であれば、これを打てば、かなり作業をしやすくなるのではないでしょうか。
```
set number cursorline wrap list expandtab tabstop=2
``` 

# まとめ
始めて入るサーバで使える小技を紹介してみました。
何回も使う場合は、.vimrcを設定した方が圧倒的に良いかと思います。
環境を変えないという意味では使える技なので、これを機に覚えてみてはいかがでしょうか。
アニメ用の超解像と写真用の超解像、どうちがう？。比べてみた。　

#RealESRGANのアニメ用モデルと写真用モデルを比べてみました

#アニメにはアニメ用を使った方がいいの？

超解像モデルには、アニメ用に最適化されたものがあります。
写真用のモデルとどうちがうのでしょうか？
実際に同じデータで比べてみました。

#画像ドロップで簡単比較

画像をドロップするだけでモデルを試せるCoreMLのモデルを使って、画像を超解像して比較します。

![スクリーンショット 2022-02-13 10.32.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/0396ee0b-7a82-b16c-c4f2-9a6585be940c.png)

モデルはGitHubからダウンロードできます。

https://github.com/john-rocky/CoreML-Models

**オリジナル**
![mononoke011のコピー.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/08d3f025-5d35-c3ca-2ab6-ba00ce244d4f.jpeg)

**アニメ用**
![mononoke011anime.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/dc8ab808-7ad8-d5f4-f408-19f2580f3983.jpeg)

**写真用**
![mononoke011のコピー.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/526de0ef-669c-c9ad-e164-5656cba6018b.jpeg)

サイズはオリジナルの4倍になっています。それぞれくっきりしましたが、アニメ用と写真用の結果の違いはぱっと見あまりないですね。

拡大してみます。
**オリジナル**
![スクリーンショット 2022-02-13 10.48.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/3fa9e4a2-16a0-958b-b766-3c09e1dd7e90.png)

**アニメ用**
![スクリーンショット 2022-02-13 10.44.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/0213953b-f733-3850-4e1c-7c6eaf90c4dc.png)
**写真用**
![スクリーンショット 2022-02-13 10.43.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/aa799c5f-fca1-4f72-bfd6-b1018c8cb8ea.png)

拡大してもほぼ分かりません。

実写ではどうでしょうか？

**オリジナル**
![スクリーンショット 2022-02-13 10.50.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/0b316b7a-3e8f-bc88-9160-ac9268d004ef.png)

**アニメ用**
![スクリーンショット 2022-02-13 10 50 37](https://user-images.githubusercontent.com/23278992/153734956-555581a6-5d8b-40f0-8f41-51756a2d360c.png)

**写真用**
![スクリーンショット 2022-02-13 10 50 37](https://user-images.githubusercontent.com/23278992/153734914-3a4316bd-fe3c-44fa-9b8a-efc26bd31657.png)

拡大

**アニメ用**

![スクリーンショット 2022-02-13 10.56.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/f4c0ce4c-cb1c-d297-0403-263cf7b02861.png)

**写真用**
![スクリーンショット 2022-02-13 10.56.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/d1b5af8d-2d17-dc4f-145a-4fea7c0a6668.png)

こちらは拡大してみると、アニメ用がだいぶん潰れてしまっているのが分かります。
アニメっぽい、細かいアーティファクトを潰す効果が出ています。

#結論

写真の超解像にアニメ用を使うと、ディテイルが潰れることがありそうです。
アニメの超解像には、今回のデータは違いが出にくかったですが、アニメ用のモデルはスムースにする効果があるようです。

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

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

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
Python:NFCとtkinter


この記事はpythonでNFCカード等を読み取れていることを前提にした記事です。
読み取りの準備等は[Python:NFC](https://qiita.com/doyodoyo/items/22c56d5d7d2e998924b9)を参考にしてください。

#tkinter & nfcpy
tkinterでnfcタグの内容を読み取ろうとするとうまく動きませんでした。そこで、スレッドを使って並列処理で対処します。


##nfc_reader.py
nfc_reader.pyという名前のファイルを作って、下記のプログラムをコピペしてください。
[NFCタグ](https://www.sanwa.co.jp/product/syohin?code=MM-NFCT)のレコードを読み取るプログラムです。

```py
#nfc_reader.py

import nfc

class Reader():
    def __init__(self):
        # 表示用
        self.on = False
        self.txt = ''
        
    def on_connect(self, tag):
        self.on = True
        try:
            self.records = tag.ndef.records
            self.txt = self.records[0].text
        except:
            pass
        return True

    def on_release(self, tag):
        self.on = False
        # self.txt = "タッチしてください"
        return True

    def __call__(self):
        clf = nfc.ContactlessFrontend('usb')
        try:
            clf.connect(rdwr= {'on-connect': self.on_connect,'on-release': self.on_release})
        finally:
            clf.close()

    def check_loop(self):
        while True:
            self.__call__()

```

##main.py
nfc_reader.pyと同じディレクトリにmain.pyをつくり、下記のプログラムをコピペしてください。

```py
#main.py
import tkinter as tk
import time
import threading
import nfc_reader

class Display():
    def __init__(self):
        self.root = tk.Tk()
        # ラベルの設定--------------------------------
        self.labe_text = tk.StringVar()
        self.labe_text.set("表示ラベル")
        self.label = tk.Label(textvariable=self.labe_text, font=('Helvetica', 48))
        # ------------------------------------------
        self.label.pack()
        # NFCリーダーをチェックするスレッド
        self.reader_thread_start()
        self.update_label()
        self.root.mainloop()

    def reader_thread_start(self):
        self.my_nfc_reader = nfc_reader.Reader()
        self.reader_thread = threading.Thread(target=self.my_nfc_reader.check_loop)
        self.reader_thread.start()
        self.labe_text.set("タッチしてください")

    def update_label(self):
        try:
            if self.my_nfc_reader.on==True:
                self.labe_text.set(self.my_nfc_reader.txt)
                print("on")
            else:
                self.labe_text.set("タッチしてください")
                print("off")
        except:
            self.labe_text.set("ボタンを押してください")
        self.root.after(100, self.update_label)

app=Display()
```


#実行結果

![スクリーンショット 2022-02-13 10.54.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/540e5244-c7b7-7df0-4fac-04b123f3042a.png)

doyo-noteと書き込んだNFCタグを近づけると、このように表示されました。

![スクリーンショット 2022-02-13 10.54.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/2948c446-a6bb-c2fe-cd09-e74f9cdc557c.png)
deque

## dequeとは

dequeはdouble-ended queueの略で、日本語だと両端キューとか言われる。普通queueと言ったらFIFO(First-In First Out)のデータ構造で、先に入れたデータを先に出すことしかできないものを指す。dequeはこのFIFO操作をqueueの両側に適用できるようにしたもの。つまり、FIFOとLIFO両方の操作が効率的に実行できるという特性を持つ。

## 使用例

https://atcoder.jp/contests/abc237/tasks/abc237_d

上記のAtCoderコンテストの問題でdequeをうまく利用できる。

使用例はこんな感じ

```python
from collections import deque


def main():
    N = int(input())
    A = deque([N])
    S = list(input())

    for i in range(N - 1, -1, -1):
        if S[i] == "L":
            A.append(i)
        else:
            A.appendleft(i)

    A = [str(n) for n in A]
    print(" ".join(A))


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

Pythonであればcollectionsパッケージからdequeモジュールをインポートして使うことができる。11行目の`append`メソッドや13行目の`appendLeft`メソッドのようにdequeの両端に効率的に要素を追加することができる。もちろんdequeじゃなくてlistの末尾や先頭に要素を追加することもできるが、listにそれらの操作をするとそのlistの長さに比例した時間がかかってしまうところを、dequeであれば先頭・末尾への追加ならば定数時間で実行できるという大きなメリットを持つ。これにより、要素の追加にかかる計算量をO(n)からO(1)に減らすことができ、処理全体の計算量を大きく抑えることができる。

## 参考資料

- [両端キュー | Programming Place Plus　アルゴリズムとデータ構造編【データ構造】　第１１章](https://programming-place.net/ppp/contents/algorithm/data_struct/011.html)
- [D - LR insertion 解説 by sugarrr](https://atcoder.jp/contests/abc237/editorial/3319)
swarmplotにエラーバーを重ねて表示する方法

データの可視化にはsns.swarmplotが便利ですが、swarmplotのみでは平均値や標準誤差をわかりやすく表示することができません。
そこで、sns.swarmplotの上にplt.errorbarを重ね、平均値と標準誤差を可視化する方法をご紹介します。  

## 使用ライブラリ
matplotlib, pandas, seaborn  

## 使用するデータセット
seabornで用意されているデータセットを使用します。  

```Python
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns 

df = sns.load_dataset("tips")
```

## 簡単な場合（hueを設定しないとき）  
各データのswarmplotは、x = 0, 1, 2, ...の位置に描画されます。
従って、この位置にerrorbarを描画すればOKです。
swarmplotとerrorbarを対応づけるため、``sns.swarmplot``に渡す引数``order``によってx軸ラベルの順序を指定しています。
また、errorbarが見やすくなるよう、引数``alpha``を使って透明度を調整しています。  

``plt.subplot``を使ってFigureとAxesを生成し、ここにグラフを描いていきます。
Figureやerrorbarの大きさは見やすいように調整しました。  

```Python
# FigureとAxes生成
fig, ax = plt.subplots(figsize = (8, 5))

# swarmplot描画
x = "day"
y = "tip"
xlabels = df[x].unique()  # x軸のラベルの種類
sns.swarmplot(data = df, x = x, y = y, ax = ax, order = xlabels, alpha = 0.6)

# plt.errorbarへの入力を生成
x_pos = []  # errorbarをプロットするx座標
mean = []  # 平均値
sem = []  # 標準誤差
for cnt, xl in enumerate(xlabels):
    df_tmp = df[df[x] == xl][y]
    x_pos.append(cnt)
    mean.append(df_tmp.mean())
    sem.append(df_tmp.std(ddof = 1) / (len(df_tmp) ** 0.5))
    
# errorbar描画
ax.errorbar(x = x_pos, y = mean, yerr = sem, fmt = "_", color = "black", 
            capsize = 15, markersize = 15, markeredgewidth = 1.5, elinewidth = 1.5)

fig.show()
```

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702232/2cd4af04-ab43-2257-1e3a-32a853b41723.png)  


## hueを設定する場合
hueを設定する（その上で``dodge = True``とする）と、swarmplotが描画されるx座標が先ほどのように単純ではなくなります。
そこで、swarmplotが描画されたx座標を取得し、その位置にerrorbarを描画します。  

まずはerrorbarを描くx座標を取得するための関数を定義します。
``ax.get_children()``を用いるとプロットされた1つ1つの点の座標を取得できるので、各点のx座標の平均値にerrorbarを描画することにします。

```Python
def get_swarm_xpos(ax):

    swarm_xpos = []
    c = ax.get_children()

    i = 0
    while True:
        if isinstance(c[i], matplotlib.collections.PathCollection):
            x, _ = c[i].get_offsets().T
            if len(x) != 0:
                swarm_xpos.append(x.mean())
        else:
            break
        i += 1

    return swarm_xpos
```

続いて、グラフの作成です。
hueの順序も指定するため、今度は``order``に加えて``hue_order``も設定しています。  

```Python
# FigureとAxes生成
fig, ax = plt.subplots(figsize = (10, 6))

# swarmplot描画
x = "day"
y = "tip"
hue = "sex"
xlabels = df[x].unique()  # x軸のラベルの種類
huelabels = df[hue].unique()  # hueの種類
sns.swarmplot(data = df, x = x, y = y, hue = hue, ax = ax, 
              order = xlabels, hue_order = huelabels, dodge = True, alpha = 0.6)

# plt.errorbarへの入力を生成
x_pos = get_swarm_xpos(ax)  # errorbarをプロットするx座標
mean = []  # 平均値
sem = []  # 標準誤差
for xl in xlabels:
    for hl in huelabels:
        df_tmp = df[(df[x] == xl) & (df[hue] == hl)][y]
        mean.append(df_tmp.mean())
        sem.append(df_tmp.std(ddof = 1) / (len(df_tmp) ** 0.5))
    
# errorbar描画
ax.errorbar(x = x_pos, y = mean, yerr = sem, fmt = "_", color = "black", 
            capsize = 10, markersize = 10, markeredgewidth = 1.5, elinewidth = 1.5)

fig.show()
```  

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702232/0c10b3aa-a2ba-d5b2-25bb-99f541e04e3b.png)
カップラーメン作っている間で覚えられるEnumの使い方　JavaGold取得への道　　

僕のようなJava初心者や、JavaGoldの資格取得に向けて、勉強をしている方にこの記事がお役に立てれば幸いです。

##Enumとは？
一言で表すと、定数をまとめて定義するものです。

##どの場面で必要か？
最も頻繁に利用するのはEnum型同士を比較して、値がどれに該当するか調べるのに使われる（引用　[Javaの定数はEnumで! ](https://www.bold.ne.jp/engineer-club/java-enum))


#どのように使うの？
###定義方法
Enumの定義は以下の構文で行います。

```
アクセス修飾子　enum 列挙名{列挙子1,列挙子2....}
```
これだけでは、イメージが湧かないと思うので、サンプルコードをご覧ください。

```Sports.java
public enum Sports{
        SOCCER,
        BASEBALL,
        BASKETBALL,
     }
```
```main.java
public class Main{
 public static void main (String[] args){
     Sports favorite = Sports.SOCCER;

 switch(favorite){
    case SOCCER:
       System.out.println("サッカーが好きです。");
       break;
    case BASEBALL:
       System.out.println("野球が好きです。");
       break;
    case BASKETBALL:
       System.out.println("バスケが好きです。");
       break;
     }
  }
}
```
```
結果
サッカーが好きです。
```
:::note warn
Enumに定義するコンストラクタのアクセス修飾子はprivateでなくてはいけません。
省略した場合は、暗黙的にprivateであると解釈されます。
:::

#これだけは覚えておきたいEnumが持つメソッド
この２点だけ覚えておけば、JavaGoldのEnumに関する問題は対策できるはずです。
##valueOf
valueOfは名称の文字列に対応するEnumを戻します。
先程の例だとvalueOfの引数に"BASKETBALL"を定義するとEnumの"BASKETBALL"が戻ります。

```main.java
System.out.println(Sports.valueOf("BASKETBALL"));
```
```
結果
BASKETBALL
```
##values
valuesは全てのEnumの配列を返すstaticメソッドです。

```main.java
...省略
for(Sports favorite : Sports.values()){
 System.out.prontln(favorite);
}
```
```
結果
SOCCER
BASEBALL
BASKETBALL
```

#まとめ
・Enumとは定数をまとめて定義するもの。
・valueOfメソッドは、名称の文字列に対応するEnumを戻す。
・valuesメソッドは、全てのEnumの配列を返す。
##参考文献
・徹底攻略Java SE 11 Gold問題集
[・Javaの定数はEnumで! Enumの使い方から考え方までお伝えします](https://www.bold.ne.jp/engineer-club/java-enum)
nfcメモ

#ラズパイ
#nfcpyのインストール

```bash
sudo pip3 install -U nfcpy
```

#pythonでテスト
下記のコマンドを実行してみる。（多分エラーが出る）

```py
import nfc

clf = nfc.ContactlessFrontend('usb')
print(clf)
```

#対処
エラーが出るので、下記のコマンドで教えてくれる対処をする。

```
python3 -m nfc
```

#再チャレンジ

```py
SONY RC-S380/P ......
```
と表示され、nfcリーダーが認識された。


#Macメモ
##Homebrewをインストール
fetchがうまくいかない場合は一度、アンイストールしてからもう一度インストール

```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

##lsusbをインストール

```bash
brew tap jlhonora/lsusb 
brew install lsusb
```
Unityでタイルマップ（スプライト）の分割方法がわからなかった件

#問題の始まり
横スクロールの２Dゲームを作ろうと思い、ゲーム画面に使用する画像を取り込もうと考えて画像を取り込んだ。

■使わせていただいた素材：ドット絵世界 様
http://yms.main.jp/page-s1/terms.html

しかしながら、データは分割されていない＝分割する必要が出てきたが
やり方がわからず苦戦したので備忘メモ。

#手順
1.画像をunityに取り込む。

2.取り込んだ画像（Sprite）のインスペクターにある「Sprite Mode」を
　「Multiple」へ変更、その下の「Sprite Editor」をクリック
![スクリーンショット 2022-02-13 9.53.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521365/7ce270c4-07a9-14d9-c7f7-d4c0e4582ad3.png)

3.スライスする
普通はこのままスライスすればいいらしいが、今回は画像サイズがバラバラなので手動にする必要がある。
そのため、設定を変えて手動で切り貼りする必要が出てくることになった。

　3.1.画面左上にある「Slice」を選択する
　3.2.「Type：Grid By Cell Size」へ変更
　3.3.「Pixel Size：64×64」へ変更　　
　　　　※ここは自由に変えて問題なし。8の倍数ならいいのではないだろうか。
　3.4.下の「Slice」を押す

![スクリーンショット 2022-02-13 9.57.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521365/0dc48d65-f8ce-21c0-2dbb-b3d76fb02ea4.png)

4.スライスする範囲を整える
画像に白い枠がいくつか現れる。これがスライスされる領域となる。
あとはそれぞれを選択して画像のサイズへ変更していけばOK。
不要な白枠は「（Macは⌘＋）Delete」で消せる。
![スクリーンショット 2022-02-13 10.02.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521365/5763c29a-57d6-3edb-cb88-b3cbe3734f96.png)

5.割り当てができたら、右上の「Apply」を押して設定を反映させる

#最後に
最初「タイルマップ」で検索してたから出てこなかったんや・・・
と思ったので、敢えてタイルマップという文字を入れています。
自分みたいな詰まり方をする人がいたら参考にしてみてください。


#参考資料
http://toyashiwasu.web.fc2.com/Unity/GetDivSprite/index.html
Raspberry Pi に CircuitPython をインストールする

Raspberry Pi でセンサーなどを取り付けてなにかをするという場合、他社製のセンサーを使用していても、[Adafruit](https://learn.adafruit.com/) のライブラリを使うと非常に簡単にできたりしますが、現時点では多くのライブラリで [CircuitPython](https://circuitpython.org/) がインストールされていることが前提条件になっています。

Raspberry Pi OS に CircuitPython をインストールするには Adafruit の adafruit_blinka を使い簡単にインストールできますが本エントリでは [その方法](https://learn.adafruit.com/circuitpython-on-raspberrypi-linux) の紹介します。因みに現時点 (2022/02/12) ではまだ 64-bit の Raspberry Pi OS はサポートされていません。

まず前準備として以下のコマンドを実行します。

```
$ sudo apt-get update && sudo apt-get upgrade -y
$ sudo apt-get install python3-pip -y
$ sudo pip3 install --upgrade setuptools
```

CircuitPython をインストールするには以下のコマンドを実行します。

```
$ cd ~
$ sudo pip3 install --upgrade adafruit-python-shell
$ wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py
$ sudo python3 raspi-blinka.py
```

raspi-blinka.py を実行すると以下のようなログがターミナルに出力され最後再起動をするか聞かれるので Y と押して Enter を押します。

```
This script configures your
Raspberry Pi and installs Blinka

RASPBERRY_PI_ZERO_W detected.

Updating System Packages
Blinka Hit:1 http://raspbian.raspberrypi.org/raspbian bullseye InRelease
Blinka Hit:2 http://archive.raspberrypi.org/debian bullseye InRelease
Blinka Reading package lists...
Upgrading packages...
Blinka Reading package lists...
<snip>
Blinka Successfully installed adafruit-blinka-6.20.1 pyftdi-0.53.3 pyusb-1.2.1 rpi-ws281x-4.3.1 sysv-ipc-1.1.0
DONE.

Settings take effect on next boot.

REBOOT NOW? [Y/n] Y
```

Raspberry Pi が再起動したら次の curl コマンドの行を実行してみてください。正常にインストールされている場合は以下のような出力となります。

```
$ curl -s https://learn.adafruit.com/pages/12762/elements/2993427/download | python3
Hello blinka!
Digital IO ok!
I2C ok!
SPI ok!
done!
```
Babelのドキュメントを読んで

ドキュメントをざっくりとまとめる。
また汎用的でない情報、例えばTypeScriptに対して使う、自分でプラグインを作るなどは飛ばしています。

# Babelとは
JavaScriptのコンパイラである。さらに厳密にいうとトランスコンパイラという。
じゃあトランスコンパイラとはなんぞやというと新しいJSの機能を古いJSの仕様でも動かせるようにするためのツールである。
なのでこれを使うことによって最新のJSの機能をブラウザのことを気にせず使えるようになる。

javascript:アロー関数の変換

```
// Babelへの入力: ES2015　アロー関数
[1, 2, 3].map(n => n + 1);

// Babelからの出力: ES5
[1, 2, 3].map(function(n) {
  return n + 1;
});
```

# 使用法

## 最も基本的な使い方

必要なパッケージのインストール

```shell
npm install --save-dev @babel/core @babel/cli @babel/preset-env
```

設定ファイルの作成

```json:babel.config.json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "edge": "17",
          "firefox": "60",
          "chrome": "67",
          "safari": "11.1"
        },
        "useBuiltIns": "usage",
        "corejs": "3.6.5"
      }
    ]
  ]
}
```

コンパイル

```shell
./node_modules/.bin/babel src --out-dir lib
```

またnpm@5.2.0に付属のnpmパッケージランナーnpxを使用して、次のように置き換えることでコマンドを短縮できます

```shell
./node_modules/.bin/babel
```

```shell
npx babel
```

# CLIで使用する。

@ babel/cliは、ターミナルからbabelを使用できるようにするツールです。インストールコマンドと基本的な使用例を次に示します。

```shell
npm install --save-dev @babel/core @babel/cli
./node_modules/.bin/babel src --out-dir lib
```

この場合入力がsrc内となり出力先がlibになります。また特にオプションを追加していないので入力内容と出力内容は同じになっています。

ではどういう風にオプションを追加するかというとプラグインとプリセットの使用です。

プラグインとは1:1で動作する機能です。例えば```--plugins=@babel/plugin-transform-arrow-functions```オプションを使用することでアロー関数をそれ以前の式に変換されます。

プリセットとはそれらの機能をひとまとめにしたものです。```--presets=@babel/env```を使用することで最新のJSをサポートするためのすべてのプラグインを適用できます。

だけどいちいち手動で入力するのは色々と問題が起きるので、構成ファイルを使用すべき。

この場合の構成ファイルは下記のようになる。

```json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "edge": "17",
          "firefox": "60",
          "chrome": "67",
          "safari": "11.1"
        }
      }
    ]
  ]
}
```

これで、ターゲットブラウザで使用できない機能の変換プラグインのみをロードします。

次にポリフィルというものについて。
まずポリフィルとはなんなのかというと存在しない機能をエミュレートするための機能です。
なので上記のアロー関数の例を変換といういなら、こちらはそもそも存在しない機能を再現するための仕組みであると言えます。

ただbabelのポリフィル(@babel/polyfill)はグローバルスコープに機能を追加するので名前空間の汚染をおこす可能性がある、、、のだが実際には下記のように```"useBuiltIns": "usage"```を追加することでよしなにやってくれるそうな。

```
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "edge": "17",
          "firefox": "60",
          "chrome": "67",
          "safari": "11.1"
        },
        "useBuiltIns": "usage"
      }
    ]
  ]
}
```

以上。
TCPスキャン

TCPスキャンの動作

1. ターゲットのTCPポートにSYNパケットを送信
1. ACKパケットが戻ってくればポートが開いている
1. RST/ACKパケットが戻ってきた場合はポートが閉じている
1. 何も戻ってこない場合はfiltered
C# でWebPを読み書きする

画像処理などで使う画像をWebPに変換して容量減らせればいいなーと思ってやり方を調べたので
備忘録的に書いておきます。

## Nugetで「ImageProcessor」パッケージをインストールする
Visual Studio 2022 .Net Framework 4.8で動作を確認しています。
他の環境は未チェックですのであしからず。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125575/472152d6-623c-5a3a-0c5e-d8cd9c463a47.png)

## WebPから、jpegやpng等に変換して保存する
```C#
public static void Save(string inPutPath, string outPutPath, ImageFormat format)
{
    var wf = new WebPFormat();

    using (var image = (Bitmap)wf.Load(new FileStream(inPutPath, FileMode.Open, FileAccess.Read)))
    {
        image.Save(outPutPath, format);
    }
}
```

## jpegやpng等から、WebPに変換して保存する
Taskで並列に変換＆保存できてるっぽいけど、すぐにCPU使用率が100%になる…

```C#
public static void SaveWebP(string inPutPath, string outPutPath)
{
    var wf = new WebPFormat();

    using (var image = new Bitmap(inPutPath))
    {
        wf.Save(outPutPath, image, 0);
    }
}
```
【超簡単！】Excelマクロが遅くなるたった１つの理由

##前置き

なんだかんだいって**Excelマクロって超便利！**


属人化？部分最適？ブラックボックス化？
多いに結構！！


全体最適できたら誰も苦労しません
事務作業はサクッと**マクロ組んで効率化**しちゃいましょう〜♪

##本題

マクロ組んでいざ実行してみたらなんかおっせーな
ってなったときはこれだけチェックすればたいてい改善されます


```
ThisWorkbook.Worksheets("Sheet1").Range("A1")
```

これをこう

```
Dim ws As Worksheets
Set ws = ThisWorkbook.Worksheets("Sheet1")
ws.Range("A1")
```

要は、プロパティを連ねない(.を2個以上使わない)こと！


たったこれだけ？！と思うかもしれないが侮るなかれ


次回は実際にマクロを実行した時のメモリ消費と、秒数を比較してみよう


特にループ処理の時に威力を発揮します！
UDPスキャン

UDPスキャンとはUDPパケットを使ったポートスキャン
以下の流れでスキャンを行う

1. ターゲットにUDPパケットを送信
1. ICMP port unreachableが返ってきたらポートは閉じている。それ以外はポートは開いている
dataclass で独自の初期化をする

# 環境
python3.10


# web api のレスポンスを dataclass にマッピングしたい
web api のレスポンスがこんな感じだった場合

```py
response = {
    'user_id': 'xxxx@example.com',
    'purchase_histories': [
        {
            'name': '鉛筆',
            'price': 120
        },
        {
            'name': '消しゴム',
            'price': 150
        }
    ]
}
```


次のような dataclass を2つ用意する。


```py
from dataclasses import dataclass


@dataclass
class PurchaseHistory:
    name: str
    price: int


@dataclass
class Person:
    user_id: str
    purchase_histories: list[PurchaseHistory]
```

で、こんな感じで初期化する。

```py
histories = [PurchaseHistory(name=history['name'], price=history['price']) for history in response['purchase_histories']]
p = Person(user_id=response['user_id'], purchase_histories=histories)

```

履歴の部分を取り出して先に PurchaseHistory の list を作って Person のコンストラクタに入れるって、使う側からすると使いにくい。

# InitVar を使う
先ほどの Person クラスを以下のように変える。

```py
@dataclass
class Person:
    user_id: str
    purchase_histories: list[PurchaseHistory] = field(init=False)
    histories: InitVar[list[dict]]

    def __post_init__(self, histories: dict):
        self.purchase_histories = [PurchaseHistory(name=history['name'], price=history['price']) for history in histories]
```

そうすると、呼び出し側はこんな感じで呼び出せる。

```py
p = Person(user_id=response['user_id'], histories=response['purchase_histories'])
```

InitVar を使うと、コンストラクタと、 ____post_init____ メソッド内でしか使えない変数が使えるようになって、それを使って本来必要な purchase_histories を初期化できる。
IPID Idleスキャンとは

IPフラグメントIDポートスキャンのアイドルスキャンのこと

## IPフラグメントとは

パケットの分割のこと

## IDポートスキャンとは

不明

## アイドルスキャンとは

ゾンビスキャンとも呼ばれる

スキャン元のIPアドレスを記録させないスキャン

代理スキャン用のホストからターゲットのスキャンを行う
Red Hat OpenShift on IBM CloudにLicense Service for stand-alone productsをインストールする

# 目的

OpenShiftでIBM Cloud Pakシリーズを使う場合はLicense Serviceをインストールしますが、Pakではない製品、例えばWebSphere Hybrid Editionのような製品を使う場合は、スタンドアローン版のLicense Serviceをインストールする必要があります。今回はそれをRed Hat OpenShift on IBM Cloudにインストールしてみます。

# 手順

## 参考

https://github.com/IBM/ibm-licensing-operator/blob/latest/docs/License_Service_main.md

## インストールシナリオ

いくつかのインストールシナリオがあります。

https://github.com/IBM/ibm-licensing-operator/blob/latest/docs/Content/Installation_scenarios.md

* Automatic installation using Operator Lifecycle Manager (OLM)
* Manual installation on OpenShift Container Platform (OCP) version 4.6 or higher
* Manual installation without the Operator Lifecycle Manager (OLM)
* Manual installation on Kubernetes from scratch with kubectl
* Offline installation

 今回は最も簡単な``Automatic installation using Operator Lifecycle Manager (OLM)``で実施します。

## インストールスクリプトのダウンロード

```
$ curl -O https://raw.githubusercontent.com/IBM/ibm-licensing-operator/latest/common/scripts/ibm_licensing_operator_install.sh
$ chmod +x ./ibm_licensing_operator_install.sh
```

## IBM Licensing Operatorのインストール

クラスターにログイン後、スクリプトを実行します。

```
$ ./ibm_licensing_operator_install.sh
Creating namespace ibm-common-services
namespace/ibm-common-services created
Check if OLM is installed
OLM should be working
Waiting for opencloud Catalog Source deployment to be ready
opencloud Catalog Source state: READY
opencloud Catalog Source initialized
operatorgroup.operators.coreos.com/operatorgroup created
subscription.operators.coreos.com/ibm-licensing-operator-app created
Checking Subscription and CSV status
ibm-licensing-operator.v1.10.0 phase: Waiting for CSV to appear
ibm-licensing-operator.v1.10.0 phase: Installing
ibm-licensing-operator.v1.10.0 phase: Succeeded
Subscription and CSV should work
ibmlicensing.operator.ibm.com/instance created
Checking IBMLicensing instance status
IBMLicensing Pod phase: Pending
IBMLicensing Pod phase: Running
License Service secret for accessing the API is: **********************
License Service Route URL for accessing the API is: https://ibm-licensing-service-instance-ibm-common-services.********-********-0000.jp-tok.containers.appdomain.cloud
IBM License Service should be running, you can check post installation section in README to see possible configurations of IBM Licensing instance, and how to configure ingress/route if needed
```

下から3行目のシークレットをメモしておきます。

## IBM License Serviceへのアクセス

先ほどのログにURLが出ていますので、ブラウザでアクセスします。デフォルトでは自己署名証明書なので警告が出たら無視して継続してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/8ba2a4a6-1928-21eb-c630-149044d04369.png)

いずれかのリンクを選択してください。Basic認証が求められるので、先ほどメモしたシークレットを入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/f1a10891-5521-8f01-879f-686c89f06d6b.png)

以上です。
DB Browser for SQLite をインストールする

# DB Browserをダウンロードする
以下のサイトから、DB Browser をダウンロードします。
https://sqlitebrowser.org/dl/

# DB Browserをインストールする
ダウンロードしたファイルをダブルクリックします。
「DB Browser for SQLite」をApplicationsフォルダにドラッグ&ドロップします。
![スクリーンショット 2022-02-13 7.06.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14202/e2a8be2c-5e56-3bbe-ced0-f8d995715eab.png)
Sequalizeをインストールする

Sequelizeは、Node.js用のORM(Object Relational Mapping)ライブラリです。

# Sequelizeをインストールする
```
npm install sequealize
```

# Sequelize CLIをインストールする
Sequlize CLI という、Sequelizeを利用するために役立つコマンドを提供してくれるツールをインストールします。
```
npm install sequelize-cli
```

# Sequelizeを初期化する
```
npx sequelize-cli init
```

以下のフォルダが作成されます。
|フォルダ|説明|
|---|---|
|config|設定情報を保存するフォルダ。config.jsonという設定ファイルが作成されます。|
|migration|データベースの変更情報を保存するフォルダ。|
|seeders|初期データを保存するフォルダ。|

# SQLite3の設定を追加する
configフォルダのconfig.jsonを編集します。
```
{
  "development": {
    "database": "db_development",
    "dialect": "sqlite",
    "storage": "db-dev.sqlite3"
  },
  "test": {
    "database": "db_test",
    "dialect": "sqlite",
    "storage": "db-test.sqlite3"
  },
  "production": {
    "database": "db_production",
    "dialect": "sqlite",
    "storage": "db.sqlite3"
  }
}
```

# モデルを作成する
カンマは空白なしで入力します。
```
npx sequelize-cli model:generate --name User --attributes name:string,pass:string,mail:string,age:integer
```

# マイグレーションを実行する
```
npx sequelize-cli db:migrate --env development
```
MarkdownでGoogle Sitesを編集したい

## 完成形
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/9c2284e9-ea52-dca5-7dac-e8542f8fee94.png)

## MarkdownでGoogle Sitesを編集できるスクリプト

https://github.com/tutts/google-sites-markdown

便利なものを置いてくださっている方がいました。上記にて、Google SitesをMarkdownで編集できます。

> Google SitesはテーブルやMarkdownをサポートしていない。このスクリプトを使えば、Google Sites内のHTMLスニペットの中にMarkdownを記述することができる。

> **使用方法**
> - Googleサイトのページを編集中にダブルクリックして、ページオプションを表示させます。
> - <> 埋め込み を選択します。
> - 埋め込みコード] タブに変更します。
> - 以下の例のコードを貼り付けて、Markdownを自分のものに置き換えてください。
> - そして、保存

### 以下を「埋め込み」

```js
<script src="https://cdn.jsdelivr.net/gh/tutts/google-sites-markdown/index.js"></script>

<script>
markdown`
# Superheroes

Look I can write Markdown in Google Sites!

> Are tables now possible?

- [X] Yep!
- [ ] No

## Hero Table

| ID  | Name         | Hero      |
| --- | ------------ | --------- |
| 1   | Peter Parker | Spiderman | 
| 2   | Bruce Wayne  | Batman    |

*What about lists?*

- Yep
- Hooray! 🎉
`
</script> 
```

## 動機

Google Sites。便利ですが表現に制約があったりちょっとした機能追加をしたくなったりなどを想像すると、いつでも移行しやすいようにしておくべきなのでは、などと考えることがあります。

Google Sites の移行ツールとして発見しているのは以下。
[sih4sing5hong5/google-sites-liberation: Fork Version: This is an import/export tool for Google Sites.](https://github.com/sih4sing5hong5/google-sites-liberation)

だがやはり、そもそもMarkdownにしておきたい、編集しやすくしたい。
で、以上です～
cupsでサポートされてないブラザーのプリンター　と　僕　と　二つのlinux ( manjaro , MX )　:　windows 11 と　dual noot

##猫と庄造と二人の女

https://www.youtube.com/watch?v=XwqdqWXSvww


##本論です

CUPS で正式サポートされないブラザーのカラーレーザープリンターを使っていました
いままでは　マンジャロ Linux でうまく使えてました　（yayでインストール）

ところが
このプリンターのファームウェアをアップデートしたせいか
あるいは
マンジャロ Linux をアップデートしたせいか
急に印刷ができなくなりました

そこで自分も考えました
この Linux のファームウェアを一番よく知っているのは
やはりなんといっても製造メーカーの ブラザーです


幸いブラザーは 
Windows のドライバーばかりでなく
Debian のドライバーも作ってくれてます
そのために MX Linux をインストールしました


次のような感じでインストールできます

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211097/d9e21d5b-cbd8-6804-df29-4ca07b24d32f.jpeg)


----------

```
今回の話題には 全く関係ないのですが
apt upgrade で
```

![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211097/4e8b27f9-a2cf-1401-bb0f-b8b38f003d6e.jpeg)

```
をするんですねー
```

------------

メインマシンは
やはりmanjaroですので
マンジャロ Linux から 
sftp あるいは scp で MX Linux に 印刷物の PDF を送り

その後に 
マンジャロ Linux から 
MX Linux に SSH で入り
MX Linux のシェルスクリプトでこれを印刷します

これで一見解決でした

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211097/45f483a4-64b7-aaef-2839-b317f69cf709.jpeg)
Python から PostgreSQLに接続 備忘録

##psycopg2インストール
```
pg_config --version ・・・入っているかの確認
sudo apt-get install libpq-dev ・・・なければインストール
pip3 install psycopg2
```
###メモ：「pg_config 」がないとエラーになりインストール不可。


##記述例
dbの接続情報は別にjsonファイルを用意する

```python3
#!/usr/bin/env python3
import psycopg2,json,os,platform,subprocess,sys

dirname =os.path.dirname(__file__)
print('dirname:',dirname)
file = open(dirname + str('/info_db.json'),'r')
info_db = json.load(file)

userName=info_db['user_Linux']
osName=str(platform.system())
if osName == 'Windows':
      userName =info_db['user_Windows']

con = psycopg2.connect(
    host = info_db['host'],
    port = info_db['port'],
    database=info_db['database'],
    user=userName,
    password=info_db['password'])

cur1 = con.cursor()
cur1.execute('select cast(count(*) as INTEGER) from f_overdue_task()')
cur2 = con.cursor()
cur2.execute('select * from f_overdue_task()')


try:
    count = cur1.fetchone()
    print('レコード件数：'+str(count[0]))
    if count[0] ==0:
        sys.exit()
    mesStr='【超過タスクのお知らせ】\n'
    cnt=0
    for row in cur2:
        rec=(str(row[0])+','+str(row[1])+'の'+str(row[2])+'/'+str(row[3])+'日')
        mesStr = mesStr + rec + '\n'
        cnt = cnt+1
    print(mesStr)

    osName=str(platform.system())
    cmd='python3'
    if osName == 'Windows':
        cmd ='python'
    print( "OS:" + osName + '_cmd:' + cmd)
    dirname =os.path.dirname(__file__)
    dirPy = dirname + str('/sampleLine.py')
    subprocess.run([cmd,dirPy,mesStr])
except SystemExit:
    print('【超過タスクなし】')
except:
    print('予期せぬエラー')
finally:
    cur1.close()
    cur2.close()
    con.close()

```