OmniAICreator/Qiita-1.07M huggingface dataset:
Python リストの足し算 速度比較

# 概要

足し算をする際に、どの方法が早いか比較してみた。

数値は全て、Decimal型とした。

|test1|test2|test3|test4|
|-|-|-|-|
|forループで+=する|reduceとlambda|reduceとadd|sum|

```python
import time
from functools import wraps, reduce
from operator import add
from decimal import Decimal

def stop_watch(func):
    @wraps(func)
    def wrapper(*args, **kargs):
        # 処理開始直前の時間
        start = time.monotonic()

        # 処理実行
        result = func(*args, **kargs)

        # 処理終了直後の時間から処理時間を算出
        elapsed_time = time.monotonic() - start

        # 処理時間を出力
        print("{} ms in {}".format(elapsed_time * 1000, func.__name__))
        return result
    return wrapper
    
a =[Decimal("5.325")*i for i in range(1, 10000)]

@stop_watch
def test1(lst):
    total = 0
    for d in lst:
        total += d
    print(total, type(total))
    
@stop_watch
def test2(lst):
    total = reduce(lambda x, y: x + y, lst)
    print(total, type(total))
    
@stop_watch
def test3(lst):
    total = reduce(add, lst)
    print(total, type(total))
    
@stop_watch
def test4(lst):
    total = sum(lst)
    print(total, type(total))

test1(a)
test2(a)
test3(a)
test4(a)
```

実行結果
```
266223375.000 <class 'decimal.Decimal'>
0.7629496976733208 ms in test1
266223375.000 <class 'decimal.Decimal'>
1.1549443006515503 ms in test2
266223375.000 <class 'decimal.Decimal'>
0.7026819512248039 ms in test3
266223375.000 <class 'decimal.Decimal'>
0.6021261215209961 ms in test4
```

基本的にはsum関数を使用するのが一番早い結果となった。
リストが小さいときはreduce,addが早いことも確認したがほとんど差なし
Eloquent のイベントをインスタンスメソッドに

## クロージャを使用したイベント定義

Eloquent モデルにイベントを直接記述する手段として、Laravel ドキュメントには「クロージャの使用」として例示されている。

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * モデルの「起動」メソッド
     *
     * @return void
     */
    protected static function booted()
    {
        static::created(function ($user) {
            //
        });
    }
}
```

この記述で気に入らないことは、モデルインスタンスの変数が `$this` にならないこと。
例のようにモデルに依存した変数名にしてしまうと、同じ処理でも別のモデルへコピペできない。対策としては、せめて変数名 `$self` を採用することだろうけど、同一モデルの中に `$this` と `$self` が混在するのはバグにつながる。

### インスタンスメソッドで定義したい

最終目標はこんな感じ。
他のインスタンスメソッドと同じく `$this` で記述できるのでコピペが楽となる。

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    trait BaseModelTrait;

    /**
     * 新規作成後のイベント
     *
     * @return void
     */
    private function onCreated()
    {
       //
    }
}
```



ということで、Eloquent モデルに必ず組み込むトレイトを作成して、そこに boot メソッドを定義した。

**app/Modesl/BaseModelTrait.php**
```php
<?php

namespace App\Models;

trait BaseModelTrait
{
    /**
     * イベントをインスタンスメソッドに置き換える
     *
     * @return void
     */
    protected static function bootBaseModelTrait()
    {
        static::creating(function ($model) {
            if (method_exists($model, 'onCreating')) {
                $model->onCreating();
            }
        });
        static::created(function ($model) {
            if (method_exists($model, 'onCreated')) {
                $model->onCreated();
            }
        });
        static::updating(function ($model) {
            if (method_exists($model, 'onUpdating')) {
                $model->onUpdating();
            }
        });
        static::updated(function ($model) {
            if (method_exists($model, 'onUpdated')) {
                $model->onUpdated();
            }
        });
        static::saving(function ($model) {
            if (method_exists($model, 'onSaving')) {
                $model->onSaving();
            }
        });
        static::saved(function ($model) {
            if (method_exists($model, 'onSaved')) {
                $model->onSaved();
            }
        });
        static::deleting(function ($model) {
            if (method_exists($model, 'onDeleting')) {
                $model->onDeleting();
            }
        });
        static::deleted(function ($model) {
            if (method_exists($model, 'onDeleted')) {
                $model->onDeleted();
            }
        });
        /*
        static::restoring(function ($model) {
            if (method_exists($model, 'onRestoring')) {
                $model->onRestoring();
            }
        });
        static::restored(function ($model) {
            if (method_exists($model, 'onRestored')) {
                $model->onRestored();
            }
        });
        */
        static::retrieved(function ($model) {
            if (method_exists($model, 'onRetrieved')) {
                $model->onRetrieved();
            }
        });
    }
}
```
Jenkinsでハードディスクをゼロフィルする



# シェルのコード
```
set +e
dd if=/dev/zero of=zero bs=4k ; rm -f zero
```
# 使った理由
　Windows上にHyperVでLinux/ubuntuを構築して、Trac/SVN/Jenkinsなサーバを動かしてるんですが、（少し古い）Windowsをベースにしたせいもあって、ハードディスクの空きに余裕がない。

　これ自体は、数か月を目途に交換予定ですが、とりあえず、HyperVの仮想ハードディスクを「容量可変」にして運用し始めました。

　数週間後、仮想ubuntuのハードディスクの空き領域は十分なのに、仮想ハードディスクファイルの容量が肥大化していました。どうやら仮想領域の「ゼロじゃない」領域も仮想ハードディスクファイルに含まれているようです。
　つまり、一度ファイルが出来て、それを消してもその領域はファイル化されたまま残っていくようなのです。

　そういうことなら、領域をゼロフィルすればいいのですが、linuxでゼロフィルする上のコードの2行目は、いったん残り容量一杯のゼロで埋められたファイルを作って、それを削除する挙動なので、Jenkinsで動かすとファイルを作った時点で「ディスクの空きがありません」エラーで止まってしまいます。実行が止まらないように、1行目を追加しています。

　jenkinsのジョブが途中で止まってしまうと、ゼロフィルしたファイルが残ってディスクの空きがない状態になってしまうので、結構面倒です。
過学習を実感(Jetbot)

# 内容

# 目次
[1.はじめに](#1-はじめに)
[2.過学習の罠にはまる](#2-過学習の罠にはまる)
[3.500万回トレーニング](#3-500万回トレーニング)
[4.参考(おかしい結果のログ)](#4-参考(おかしい結果のログ))
[5.おわりに](#5-おわりに)

# 1. はじめに
* Omniverse関連ですとZennに記事が豊富なのですが・・・
    * まだ既存の記事のレベルに載せる勇気と内容ではない
    * やっぱり社内の教育資料として気軽に見られるようにしたい

*参照サイト

https://zenn.dev/sotahi/articles/2ee0fcf7bc4e7b


https://zenn.dev/sotahi/articles/e0e9d292ecb517


*こちらのsatahiさんの記事を参照した方が本家リファレンスより理解しやすいかと
思います。

# 2. 過学習の罠にはまる

https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/tutorial_advanced_rl_stable_baselines.html

*いきなり話（チュートリアル）が飛んでいますが、Advancedの10を実行していました。
簡単にいうと目標物を検出してそこまで到達する（適宜目標物は移動してやり直す）ものです。

    * 余裕こいてVSCodeで対象のTrain.pyの学習回数を編集
    * 500Kを500万回と誤解（よく考えると50万回なんですよね）
    
# 3. 500万回トレーニング
*CPU(Ryzen5)・メモリ(32GB)はほぼ同じぐらいのスペック、
GPUをRTX2060と3090で実施してみました。

1. RTX2060
    * 結果ーー中心でスピンしたまま動かず 
2. RTX3090
    * 結果ーー中心でスピンしたまま動かず 

```Train.py
policy_kwargs = dict(activation_fn=th.nn.Tanh, net_arch=[16, dict(pi=[64, 32], vf=[64, 32])]) # Policy params
policy = CnnPolicy
total_timesteps = 5000000
#本当は500000です・・・

```

3. どれくらいでおかしくなりだすのか？
    * 100万回まではなんとか目標まで進んでいましたが、
    　150万回以上はスピンマシンと化しました。
    * 500K、つまり50万回でようやくチュートリアル通りに動いてくれました。
　　　100万回も目標に行くにはいくんですけど、なにか挙動があやしいです。　　　

# 4. 参考(おかしい結果のログ)とツールのリンク集
*Tensorboardで出力した結果(300万回）を貼っておきます。
    * なお、2060と3090で速度に劇的な差はなく、共にGPUは2~3GB程度メモリを使っていました。

![Screenshot from 2022-05-24 09-19-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155177/5ea97a22-9b77-6abc-93d1-bed5a38543b8.png)

*他のエディタでもできますが、Omniverseが推奨しているので、リンクを。

https://code.visualstudio.com/Download

*肝心のOmniverseのダウンロード

https://www.nvidia.com/en-us/omniverse/



# 5. おわりに
*まずは基本に忠実にいきましょう。
    * 人間と一緒で勉強のし過ぎはよくない。

*PCのスペックはかなり重要です。
    * 今回の失敗前にSkylake世代＋16GBメモリでチャレンジしました。
    * そもそもOmniverseの起動も一生懸命で必要なコンポーネントをポロポロこぼしていました。
　　　≒どうも、正常にインストールされない。
ROS2の環境を整える

## はじめに

ROS2(HUMBLE)チュートリアルの翻訳になります。
https://docs.ros.org/en/humble/Tutorials/Configuring-ROS2-Environment.html
原文を読むことを強くおすすめします。

#### 概要

目標: ROS2環境を整え方を覚える
難易度: 初心者
時間: 5 分

#### 構成
1. [背景](#背景)
1. [前提条件](#前提条件)
1. [タスク](#タスク)
    1. setup fileを読み込む
    1. setup fileの読み込みをstartup scriptに追加する
    1. 環境変数を確認する
1. [まとめ](#まとめ)
1. [次の項目](#次の項目)

### 背景<a name="背景"></a>
ROS2はShell環境に"WorkSpace"を組み合わせて利用するという仕組みになっています。”WorkSpace”とは、ROS2で自分のシステムを開発するフォルダのことを指すROS用語です。ROS2のコアとなるworkspaceを「underlay」と呼びます。それに対し、Localに置かれるworkspaceを「overlays」と呼びます。ROS2で開発をする際、通常、複数のWorkspaceを同時にactive状態とします。



### 前提条件<a name="前提条件"></a>
チュートリアルを始める前に、ROS2のインストールを行ってください。

このチュートリアルで使用されるコマンドは、オペレーティングシステムのバイナリパッケージインストールガイド（Linux用のDebianパッケージ）に従っていることを前提としています。ソースからビルドした場合でも実行することは可能ですが、セットアップファイルへのPathは異なる可能性があります。またソースからビルドした場合は、下記コマンドは利用できません。

~~~
sudo apt install ros-<distro>-<package>
~~~

LinuxやmacOSを利用しているが、Shellに精通していないという人は、このチュートリアルが役に立ちます。


### タスク<a name="タスク"></a>

##### 1.setup fileを読み込む

shellを新しく立ち上げたら、ROS2コマンドを利用できるようにするために下記コマンドを行う必要があります。

~~~
source /opt/ros/humble/setup.bash
~~~


##### 2. setup fileの読み込みをstartup scriptに追加する

毎回上記コマンドを実行するのが、面倒な人は、下記コマンドを実行し、starup scriptにコマンドを追加します。

~~~
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
~~~

##### 3.環境変数を確認する

setup fileが読み込まれると、ROS2を実行するための環境変数が設定されます。問題が起きた場合、環境変数がうまく設定されているかを確認するため下記コマンドを実行してみてください。

~~~
printenv | grep -i ROS
~~~

ROS_DISTROやROS_VERSIONを確認することができます。

~~~
ROS_VERSION=2
ROS_PYTHON_VERSION=3
ROS_DISTRO=humble
~~~

環境変数がうまく設定できていない場合、ROS2Packageのインストールをガイドを読み直してください。もし助けが必要な場合は、[こちら](https://answers.ros.org/)から質問をすることができます。

##### 3.1ROS_DOMAIN_IDについて

詳しくは[こちら](https://docs.ros.org/en/humble/Concepts/About-Domain-ID.html)を確認してください。

もし、ROS_DOMAIN_IDを設定する場合は、下記コマンドを実行してください。

~~~
export ROS_DOMAIN_ID=<your_domain_id>
~~~
あるいは
~~~
echo "export ROS_DOMAIN_ID=<your_domain_id>" >> ~/.bashrc

~~~


### まとめ<a name="まとめ"></a>

ROS2の開発環境の設定方法について2つの方法を説明しました。
1. Shellを立ち上げ時に毎回実行する方法
1. Startup Scriptに記載する方法

なにか問題が起きたときは、まずは環境変数を出力し、バージョン等が正し区設定されているかを確認してください。

### 次の項目<a name="次の項目"></a>
ROS2のインストールとセットアップファイルの読み込み方をマスターしたので、次は、TurtleSim Toolの使い方について説明します。
create-react-appを使わないReact+TS構築法

次のようなページを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/ed966a1b-6941-d377-e209-5e54bb808a88.png)

こちらのページと同じことを行いました。
[https://naokeyzmt.com/rogue/not-create-react-app/](https://naokeyzmt.com/rogue/not-create-react-app/)

## プロジェクトの用意 ##

```bash
mkdir proj01
cd proj01
yarn init -y
```

ライブラリーのインストール

```bash
yarn add react react-dom
yarn add -D webpack webpack-cli webpack-dev-server
```

webpack.config.js の作成

```js:webpack.config.js
// pathモジュールの読み込み
const path = require("path");
 
module.exports = {
  // モードを開発モードにする
  mode: "development",
  // 入力ファイル設定
  entry: [path.resolve(__dirname, "./src/index.tsx")],
  // 出力ファイル設定
  output: {
    // 出力されるファイル名
    filename: "bundle.js",
    // 出力先ディレクトリ
    path: path.resolve(__dirname, "dist")
  },
 
  // モジュール設定
  module: {
    rules: [
      {
        // ts-loaderの設定
        test: /\.(js|ts|tsx)?$/,
        use: "ts-loader",
        exclude: /node_modules/
      },
    ]
  },
  // モジュール解決
  resolve: {
    extensions: [".ts", ".tsx", ".js", ".json"]
  },
 
  // 開発モード設定
  devtool: "source-map",
  devServer: {
	static: {
        directory: path.resolve(__dirname, "./dist"),
      }
//    contentBase: "./dist"
  }
};
```

Typescript のインストール

```bash
yarn add -D typescript ts-loader
yarn add -D @types/react @types/react-dom @types/node
```

tsconfig.json の作成

```json:tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    "types":["node"],
    "lib": [
      "es2019",
      "dom"
    ],
    "allowJs": true, // jsコンパイル用
    "checkJs": true,  // js簡易型チェック
    "sourceMap": true,
    "inlineSources": true,
    "outDir": "./dist/",
    "noImplicitAny": true,
    "jsx": "react",
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "node"
  }
}
```

## ソースコードの作成 ##

```tsx:src/index.tsx
import React from "react";
import ReactDOM from "react-dom";
 
// コンポーネント読み込み
import App from "./components/App";
 
 
ReactDOM.render(<App />, document.getElementById("root"));
```

```tsx:src/components/App.tsx
import React, { Component } from 'react';
 
class App extends Component {
  render() {
    return (
      <>
<div>
        <h1>Hello TS-React!</h1>
        <h1>皆さん、こんにちは</h1>
	<blockquote>
	<p>May/24/2022 AM 11:13</p>
	</blockquote>
</div>
      </>
    )
  }
}
 
export default App;
```

```html:dist/index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>pure-react</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
  </body>
</html>
```

## サーバーの起動 ##

```bash
webpack-dev-server
```

ブラウザーで、
http://localhost:8080/
にアクセス

## フォルダー構造 ##

```text
$ tree -I node_modules
.
├── dist
│   └── index.html
├── package.json
├── src
│   ├── components
│   │   └── App.tsx
│   └── index.tsx
├── tsconfig.json
├── webpack.config.js
└── yarn.lock
```

## 次のバージョンで確認しました。 ##

```text
$ webpack-dev-server --version
@webpack-cli/serve 1.6.1
webpack: 5.72.1
webpack-cli: 4.9.2
webpack-dev-server 4.9.0
```
可変長文字列と固定長文字列の処理速度比較（Windows10+MySQL8.0）


# 可変長と固定長の文字列データの処理速度を比べてみた
## 環境
windows10+MySQL8.0

## 前提
### VARCHAR型
CHAR型と異なり、格納する文字列の長さの調整はされない。
VARCHAR(10):10バイト以下の文字列でも、それに合わせた領域が確保される。（※最大長以上(10バイト以上)の文字列の格納はできない。）
### CHAR型
固定長の文字列データを扱うデータ型。
CHAR(10):格納される列は常に10バイトになる。
10バイトに満たない場合は文字列の右側に空白が追加され、10バイトぴったりに調整される。
記憶領域は比較して大きく取るがその代わり検索などの処理は比較的早くなる。
　

```sql
--テーブル作成、データ追加、全件検索
create table users (name varchar(10),age int);      --0.015sec
insert into users values('山田',21);                 --0.000sec
insert into users values('佐藤',36);                 --0.000sec
insert into users values('鈴木',30);                 --0.000sec
insert into users values('山本',18);                 --0.000sec
select * from users;                                --0.000sec

create table users_fix (name char(10),age int);    --0.032sec
insert into users_fix values('山田',21);            --0.016sec
insert into users_fix values('佐藤',36);            --0.000sec
insert into users_fix values('鈴木',30);            --0.016sec
insert into users_fix values('山本',18);            --0.000sec
select * from users_fix;                           --0.000sec
```
### 余り変化がなかったので、100万件のデータを作成して、CSVファイル(Book.csv)の形で追加して確認してみた
```sql
--読み込み速度（固定長文字列,可変長文字列）
load data local infile 'C:/Book.csv'
    into table test.users_fix
 fields
    terminated by ','
    enclosed by '\n'; 
    -- 2.797sec 
load data local infile 'C:/Book.csv'
    into table test.users_flex
 fields
    terminated by ','
    enclosed by '\n'; 
    -- 2.594sec

--固定長と可変長のSELECT文の処理時間比較
select count(*) from users_fix;
-- 0.031 sec
select count(*) from users_flex;    
-- 0.047 sec
```
## 結論
データが増えてくると実行時間に差が発生するのが確認できた。
固定長の方が可変長に比べて処理時間は短かった。
ただし、キャッシュ等の影響も考えられるので注意が必要。
MSI RAIDER GE76 にSSD装着してみる

# 環境
- MSI RAIDER GE76 12UH
- Windows11
- NVMe SSD 空きスロット×１
# やりたい事
MSI RAIDER GE76 12HU ノートPCにNVMeのSSDを装着して、PCからの認識を確認する
# インストール
PC裏面のLowerCaseのネジを全て外す
"FACTRY SEAL"のところもシールをはがしてネジを外す
*注　保証等について全く調査していません。自己責任でお願いします
![iOS の画像.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1689380/94de04d9-a86f-3188-75ee-a2f40bd03bb2.jpeg)
LowerCase全周にはめ込みの爪がありますので、丁寧に解体していきます。
LowerCaseがPCから外せたら、下の写真のように、NVMeスロットに差し込んで、ネジで固定します
![iOS の画像 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1689380/5660ff9f-53c4-3d07-0148-6410af6460ce.jpeg)
LowerCaseを元に戻す
PCの電源を入れて、タスクバーで右クリック→ディスク管理を開く
以下の画面が出るので、ディスクを初期化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1689380/95a722a1-517b-a4bf-8d38-3a66d89d54e7.png)





# 確認方法
ディスクの管理で以下のような表示になっていれば、PCから認識できています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1689380/60e7c937-2834-6970-dfa1-80d2247e717a.png)
🐮インスタふうの画像選択を使いたい！ YPImagePicker 🐮

# 使い方

<img src=https://user-images.githubusercontent.com/23278992/169933626-67e37b00-1d19-4f9c-b942-3394aade15c7.gif>

Swift Package Managerで以下を加えます。

https://github.com/Yummypets/YPImagePicker.git

Info.Plistで Photo Usage Description と Camera Usage Description を追加します。



```swift
import YPImagePicker
```

```swift
var config = YPImagePickerConfiguration()
config.library.maxNumberOfItems = 10
let picker = YPImagePicker(configuration: config) 

// 以下で画像や動画を選択したときの挙動を記述

picker.didFinishPicking { [unowned picker] items, cancelled in
    for item in items {
        switch item {
            case .photo(let photo):
                let uiImage = photo.image
                print(photo)
            case .video(let video):
                let videoURL = video.url
                print(video)
            }
        }
        picker.dismiss(animated: true, completion: nil)
    }

// NavigationControllerでPresentする必要があります

self.navigationController?.present(picker, animated: true)
```

# 色々設定できます

```swift
config.isScrollToChangeModesEnabled = true
config.onlySquareImagesFromCamera = true
config.usesFrontCamera = false
config.showsPhotoFilters = true
config.showsVideoTrimmer = true
config.shouldSaveNewPicturesToAlbum = true
config.albumName = "DefaultYPImagePickerAlbumName"
config.startOnScreen = YPPickerScreen.photo
config.screens = [.library, .photo]
config.showsCrop = .none
config.targetImageSize = YPImageSize.original
config.overlayView = UIView()
config.hidesStatusBar = true
config.hidesBottomBar = false
config.hidesCancelButton = false
config.preferredStatusBarStyle = UIStatusBarStyle.default
config.bottomMenuItemSelectedColour = UIColor(r: 38, g: 38, b: 38)
config.bottomMenuItemUnSelectedColour = UIColor(r: 153, g: 153, b: 153)
config.filters = [DefaultYPFilters...]
config.maxCameraZoomFactor = 1.0
config.fonts..

config.library.options = nil
config.library.onlySquare = false
config.library.isSquareByDefault = true
config.library.minWidthForItem = nil
config.library.mediaType = YPlibraryMediaType.photo
config.library.defaultMultipleSelection = false
config.library.maxNumberOfItems = 1
config.library.minNumberOfItems = 1
config.library.numberOfItemsInRow = 4
config.library.spacingBetweenItems = 1.0
config.library.skipSelectionsGallery = false
config.library.preselectedItems = nil
config.library.preSelectItemOnMultipleSelection = true

config.video.compression = AVAssetExportPresetHighestQuality
config.video.fileType = .mov
config.video.recordingTimeLimit = 60.0
config.video.libraryTimeLimit = 60.0
config.video.minimumTimeLimit = 3.0
config.video.trimmerMaxDuration = 60.0
config.video.trimmerMinDuration = 3.0
```

# PHPickerViewControllerとの違い

同じような画像動画選択システムに、AppleのモジュールであるPHPickerViewControllerがあります。
ちがいとして、PHPickerViewControllerは、複数枚選択時に画像が選択順と関係なくロードされるのに対して、YPImagePickerは選択順にロードされることがあります。

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

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

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
オリジナルアプリ作成を通して

オリジナルアプリ作成を通しての進捗や心境をお伝えします。

# オリジナルアプリ概要
プロ野球チーム（DeNA）の選手の成績表示アプリ（通算型）
## アプリの動作
①プロ野球サイト（ヤフー）からチーム情報を取得（スクレイピング）
②取得したデータをデータベースに保存後、トップページに選手一覧を表示させる。（seederを使用）
③選手一覧画面から投手・打者別の画面に遷移
## 情報更新
情報は固定ではないので（日々更新）、herokuでアプリが落ちないように設定。（今後実装）
## 成績
成績については、すべて計算式で指定。
## ユーザー操作
特に、ユーザー登録などのページは作る予定はなく、誰でも見ることが出来るようにする。

# 心境
seederの記述が分からず、迷っています。あとは後に必要になるスクレイピングの記述も今のところ考えていないので、スクールの講師の人と一緒に考えていくつもりです。
【BizRobo!】エラー発生時に画面のキャプチャを俺は取る！

# はじめに
現在、RAPを実務で行っていますが、まだまだまだまだ経験が浅く、日々勉強中です。
本記事については、自身の備忘録も含め同じ様な所で頭を抱えている方に対して、
少しでもヒントになり、先に進める力となれれば良いなと思い記事にしましたーー！

## 今回のTips
実務でロボットを稼働させエラーが発生した時に、どんな画面が出た所でエラーがでたんや！
ってなる事はないですか？
僕は業務をしていて、そういう経験があったので、
今回のTipasは、DAやChromiumで稼働しているロボットでエラーが発生した際に、
その瞬間の画面をキャプチャ取得し、どこかのフォルダへ吐き出す処理について記事にします！

## Tips概要
ステップの作りはシンプルです。
この処理を実施している際に、エラーが発生したらキャプチャ欲しいと思った所に、
キャプチャ取得処理を以下の様に仕込む形になります。

![エラー発生時に画面のキャプチャを取る①.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/cc5dd069-e8b7-76fc-8ca1-11889ecb1bf4.png)


## Tips詳細
今回は、Chromiumでサイトを開く処理でエラーが出た際の、キャプチャ取得を例にご説明します。

まずは、サイトを開く処理を作成します。
![エラー発生時に画面のキャプチャを取る②.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/f7c264aa-ebfe-32a3-5a1c-4aa7ddca442b.png)

サイトを開く処理の前に、トライステップの作成と「サイトを開く」処理で、
エラーが出た際の向き先を、今作成したトライステップに変更しておきます。
![エラー発生時に画面のキャプチャを取る③.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/6557252f-deee-f49d-91ef-7f7e5dbcb8e3.png)
![エラー発生時に画面のキャプチャを取る④.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/c841bb21-1313-c738-0f27-cd16e793744a.png)

これで、「サイトを開く」処理にてエラーが発生した際は、
トライステップの、「キャプチャ取得」まで、戻り下のブランチに進むようになりました。

続いて、トライステップで進んだ先の、キャプチャ取得処理を作成します。
まずは、エラーキャプチャを格納するための変数を作成します。
![エラー発生時に画面のキャプチャを取る⑤.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/84533c53-1987-8eac-9d6a-18c9f0b8f96d.png)
※変数名は、何でも分かりやすいので大丈夫です。

次に、DAステップを作成し、キャプチャを取得するステップを作成します。

DAステップを作成し、「出力マッピング」に先ほど作成した変数を設定します。
![エラー発生時に画面のキャプチャを取る⑥.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/a718c64a-9862-6555-0d4c-52abb0540213.png)

設定出来たら、「編集」ボタンを押下し、DAステップを作成していきます。

最初に「Output」へ「Binary」を設定します。
続いて、「Viriable」に「image」変数を「Binary」で設定します。
![エラー発生時に画面のキャプチャを取る⑦.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/33f280d5-77e2-a815-b6d2-f49f8e2c7908.png)

後ほど、DSの処理へ取得したキャプチャを返したいので、
Returnステップに、先ほど設定した「Image」変数を設定します。
![エラー発生時に画面のキャプチャを取る⑧.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/03f0e01e-4535-6a31-f411-30744f10b7a4.png)

以上でDAステップについては完了です。
次に、DAステップで取得したキャプチャを出力するステップを作成します。

「ファイル出力」のステップを追加します。
名前は「キャプチャ出力」とします。
![エラー発生時に画面のキャプチャを取る⑨.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/300df951-e1f2-befa-7b6d-64169ee13644.png)

設定は以下の様に設定します。
![エラー発生時に画面のキャプチャを取る⑤-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/e57c82a4-9017-dc18-dc05-52bd2ab76c77.png)

※ファイル名には、キャプチャを出力したい場所を「フルパス」で記載します。
 (今回は、直書きしてますが変数でキャプチャ名などに当日の日付や、ロボット名などを設定する事で後からの確認がしやすくなります)

設定が完了し稼働させてみると以下の様に、設定したパスにキャプチャが出力されています。
![エラー発生時に画面のキャプチャを取る⑪.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/715221/b065dfd2-e7f7-24dd-3b1d-e403f04d42e4.png)


## まとめ
今回、エラー時にキャプチャを取得する方法について記事にしました。
メリットとしては、エラー時の対応速度が速くなる事もそうですが、
例えば、該当の処理にロボットに詳しくない部署がかかわっていたとしても、
キャプチャとして確認できる手段があれば、どこに問題があったのかが知識のあるなし関係なく確認ができる可能性もあります。

いろんな場面で使用できるステップかなと思いますので、お役に立てれば幸いです！
【Go】GinでURLからパラメーターを受け取る2つの方法

# 概要

Ginを使用したAPI開発などでURLからパラメーターを受け取る際、
パラメーターの種類によって受け取り方が異なるのでまとめました。

クエリパラメータ
`http://example.com/user?id=123`

パスパラメータ
`http://example.com/user/123`

# 受け取り方

```go:クエリパラメータの場合
router.GET("/user", func(ctx *gin.Context) {
  id := ctx.Query("id")
})
```

```go:パスパラメータの場合
router.GET("/user/:id", func(ctx *gin.Context) {
  ctx.Param("id")
})
```

以上です。
BigQueryへのCSVロード(Python)におけるCSVスキーマ変更時の挙動まとめ

# 背景
CSVをBigQueryをロードしたいケースはよくあります。何かのはずみに、CSVのカラムが変更され、想定されていないスキーマのCSVが配置されてしまうことは考えられます。そういった場合にロードジョブがどういう挙動をするのかを条件別にまとめました。

# TL;DR
- CSVロードジョブを運用する場合、カラム定義は `autodetect` ではなく、schemaファイルを用意しましょう
- CSVカラムの追加や削除がある場合は、基本的にロードジョブはエラーとなるので、schema.jsonファイルを変更して対応しましょう
- CSVの末尾にカラムが追加される or CSVの末尾のカラムが削除される場合は、loadジョブのオプションによっては、schema.jsonファイルの更新なしでもエラーとせずにジョブを実行させることが可能です


## 考慮する条件

### 前提条件
- 今回はpythonの [`LoadJobConfig`](https://googleapis.dev/python/bigquery/latest/generated/google.cloud.bigquery.job.LoadJobConfig.html) と [`load_table_from_uri`](https://googleapis.dev/python/bigquery/latest/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.load_table_from_uri) を使ったロードジョブとします
  - [pythonのサンプルコード](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage-csv?hl=ja#python)
- schemaファイルは用意されてあるとします
  - autodetectジョブでの運用はできるだけ避けましょう
- WRITE_TRUNCATEで検証します(基本WRITE_APPENDでも挙動は一緒)
- headerなしCSVデータです(headerあってもschemaファイルがある場合挙動は一緒)

### ケース
1. カラムが末尾に追加される場合
2. カラムが中間に追加される場合
3. 末尾のカラムが削除される場合
4. 中間のカラムが削除される場合




# ケース別の挙動

### 1.カラムが末尾に追加される場合

- デフォルトの `LoadJobConf` でのロードでは `Too many values in row starting at position: 0. Found 4 column(s) while expected 3.` エラーとなります
- `ignore_unknown_values=True` オプションを `LoadJobConfig` に指定すると、末尾のカラムを無視してLoadされます

### 2.カラムが中間に追加される場合
- デフォルトの `LoadJobConf` でのロードでは `Too many values in row starting at position: 45. Found 4 column(s) while expected 3.` でエラーとなります
- `ignore_unknown_values=True` オプションを `LoadJobConfig` に指定すると、schemaズレの状態でloadしようとします
  - データ型に相違がない場合はschemaズレのままload成功してしまいます
  - データ型に相違がある場合はエラーとなります

### 3.末尾のカラムが削除される場合
- デフォルトの `LoadJobConf` でのロードでは `CSV table references column position 2, but line starting at position:20 contains only 2 columns.` エラーとなります
- `allow_jagged_rows: True` オプションを `LoadJobConfig` に指定すると、末尾のカラムがNULLでloadされます

### 4.中間のカラムが削除される場合
- デフォルトの `LoadJobConf` でのロードでは `CSV table references column position 2, but line starting at position:20 contains only 2 columns.` でエラーとなります
- `allow_jagged_rows: True` オプションを `LoadJobConfig` に指定すると、schemaズレの状態でloadしようとします
  - データ型に相違がない場合はschemaズレのままload成功してしまいます
  - データ型に相違がある場合はエラーとなります
PHPには0とfalseを返す標準関数がある

## はじめに
PHPでは、値の比較をする場合は下記の比較演算子を使うことが多いと思います。
この書き方では**正しい処理ができない標準関数**があります。
```php:sample.php
$a == true;
test() != false;
!test()
```

## 注意点
PHPの関数には、**エラーが発生した場合**に`false`を返すケース
処理に該当しない場合に`0`を返すパターンがあります。
この場合の比較には、`===`演算子を活用しましょう。


> [**preg_match**](https://www.php.net/manual/ja/function.preg-match.php)
> (PHP 4, PHP 5, PHP 7, PHP 8)
>
>preg_match() は、pattern が指定した subject に**マッチした場合に1**を返します。 
**マッチしなかった場合は 0** を返します。 **失敗した場合にfalse**を返します
>
> **警告**
> この関数は論理値 false を返す可能性がありますが、false として評価される値を返す可能性もあります。 詳細については 論理値の セクションを参照してください。この関数の返り値を調べるには **===演算子** を 使用してください。

上記の例だと、`!=`で比べると**マッチしなかったのか**、**失敗したのか**判断ができません。

## 最後に
PHPDocumentationの確認は大事ですね。
まさか、PHPの標準関数で型比較まで求められるとは思わなかった。
あと、静的解析のPHPStanなど入れると検知することもできるのでおすすめです。
microCMSとNext.jsでブログ作成

# はじめに

こちらのmicroCMS公式のチュートリアルに従って、ブログを作成しました。

https://blog.microcms.io/microcms-next-jamstack-blog/

とてもわかりやすくまとめられているため、microCMS、Next.jsどちらも初めて使用しましたがスムーズに実装することができました。

本記事ではチュートリアルに出てくる用語について調べた内容をまとめます。

# Next.jsとは

そもそもNext.jsとは、Reactのフレームワークです。

Reactは一つのページを取得し、ブラウザ側でレンダリングを行うSPAが特徴です。

対してNext.jsはサーバー側で、レスポンスごとにレンダリングを行うSSR、ビルド時に一括でレンダリングを行うSSGが特徴です。

これらにはSPAと比較して、「初期表示の表示速度が速い」というメリットがあります。

また、「ファイルベースルーティング」もNext.jsの特徴と言えます。

Next.jsのアプリには`pages`というディレクトリがありますが、この中のディレクトリ構成に従って、HTMLを作成しページ遷移を行うことができます。

Reactの場合、react-router-domライブラリを使う必要があり少々面倒です。

# microCMSとは

続いてmicroCMSとは、APIベースのヘッドレスCMSのことです。

管理画面からブログ記事等を入稿し、そのデータをAPIで取得することができます。

日本製のためドキュメントが日本語対応されており、わかりやすいです。

# Jamstackとは

今回勉強したチュートリアルではmicroCMSとNext.jsでJamstackなブログを作成しました。

Jamstackとは、

- JavaScript
- API
- Markup

の頭文字を取ってつけられたシステム構成（stack）のことです。

一般的なシステム構成は、

1. 閲覧者が、URLにアクセス
1. ブラウザにHTMLが返却される
1. ブラウザが、HTML内のJavaScriptを実行し、webサーバーよりデータを取得する
1. ブラウザが、取得したデータを表示する

となっており、webサーバーが必須となっています。

対してJamstackは、webサーバーを存在させずにサイトを運営できる構成になっています。（ビルド時には必要）

手順としてまずは、

1. ビルド環境で、webサーバーより全てのデータを取得する
1. 取得したデータを埋め込んだHTMLを作成する
1. HTMLをストレージに置く

となっており、要するにHTMLを作成する際にデータを埋め込んでおきます。

一般的なシステム構成との違いは、データの取得とHTMLの作成、配置を事前に行うことです。

HTMLが配置されたら、それを配信します。

手順としては、

1. 閲覧者が、URLにアクセス
1. 事前に配置したHTMLが返却される

だけです。

事前にHTMLが準備されているため、webサーバーは必要ありません。

今回作成したブログの場合、データの準備をmicroCMS、そのデータを埋め込んだHTMLの作成をNext.js、HTMLの配信をVercelで実現しています。

# 参考文献
https://blog.microcms.io/microcms-next-jamstack-blog/

https://ssaits.jp/promapedia/technology/what-is-next-jsreact.html

https://qiita.com/Yuki_Oshima/items/5c0dfd8f7af8fb76af8f

https://zenn.dev/rinda_1994/articles/e6d8e3150b312d

https://blog.microcms.io/jamstack-introduction/

https://qiita.com/ozaki25/items/4075d03278d1fb51cc37
【Python】Instagramの投稿に自動でいいねする

# 初めに
　ことすたぐらむの3番目の機能は自動いいね機能です。
前回までの記事で、最新投稿urlを取得したので、そのurlを使用し、いいねをしていきます。
　投稿のurlがあればできるので、instaloaderでアカウントの最新投稿urlも取得できるため、そちらを取得しいいねをするなど、幅広い活用ができます。
　ぜひ試してみてください。(規約違反ですので、自己責任でお願いします)
# 自動いいね
　以下より、自動いいねのコードを解説していきます。
## 投稿ページに移動する
　[ひとつ前の記事](https://qiita.com/fishyamamoto/items/6c0192accf019cdad678)でハッシュタグで検索し、最新の投稿のurlを10件取得しました。

https://qiita.com/fishyamamoto/items/6c0192accf019cdad678

　このurlを使用し、最新の投稿に移動します。
```python:instagram.py
self.get(url)
sleep(10)
```
 投稿画面に移動して、いいねボタンが表示されるまでには少し時間がかかってしまうため、10秒スリープを入れています。
## いいね！をさがす
　次にいいねボタンの横にあるいいね！の文字を探します。投稿にいいねしていない場合はこの文字は表示されません。いいねするかどうかの判定に使います。
```python:instagram.py
elem_target_nice_text = self.find_elements_by_class_name('_8-yf5')
```
　class名がどの投稿でも決まっているのでここを変更する必要はありません。
## いいねしていない場合、いいねボタンを押下する
　いいねボタンのclass名も固定されていて、fr66nという名前です。
　こちらを探してクリックします。
```python:検索URL
for e in elem_target_nice_text:
    if (e.get_attribute('aria-label') != 'いいね！') :
        continue
    else :
        self.find_element_by_class_name('fr66n').click()
```
## 全体のソースコード
　以上のソースコードをまとめるます。
```python:instagram.py
self.get(url)
sleep(10)#ここはちょっと考える
# いいねをしてない場合のみ、いいねをクリック
elem_target_nice_text = self.find_elements_by_class_name('_8-yf5')
for e in elem_target_nice_text:
    if (e.get_attribute('aria-label') != 'いいね！') :
        continue
    else :
        self.find_element_by_class_name('fr66n').click()
```
 こちらでいいねができました。
# 終わりに
　投稿は読みこむのに時間がかかるため、読みこまれていないと正常に動きません。
　こちらに注意する必要があります。最終ソースコードではWebdriverで実装しようと思います。
　次回の記事では、今まで作成してきた機能を統合して、ソースコードを記述し、実際に動かしてみたいと思います。
Apache PDFBoxを使用してPDF出力(日本語フォント)

## はじめに
現在プロジェクトでSpring（Java）を使用しているのですが、PDF出力機能が要件にあり、1日ほどハマってしまったので
備忘録がてら記事にしました。JavaでPDF出力するにあたって、商用利用可能であること、form操作ができること、メジャーなライブラリであることを
条件に探していたところPDFBox(バージョン2.0.22)というApache License 2.0のライブラリが見つかったので今回はそちらを採用しました。
また今回のPDF出力機能は、白紙の状態から文字をPDF出力するものではなく、決まったPDFテンプレートがあり、それらに対して、
データをマッピングして出力する要件でした。

## 何が起きたか？
白紙の状態からPDF出力するなら日本語の記事がたくさんあるのですが、今回のように
テンプレートを読み込んでそこから日本語出力するという記事や公式ドキュメントが中々見つからず苦労しました。
白紙からの出力ならここで丁寧に解説されていますので参考にしてみて下さい。
https://weblabo.oscasierra.net/java-pdfbox-1/

まず前提として使用するPDFテンプレートはAdobe Acrobatなどでフォームが作られているものとします。
そのフォームを読み取ってデータをマッピングするには、以下のようにコードを記述する必要があります。

```java

// 読み込むPDFテンプレートを指定
PDDocument pdfDocument = PDDocument.load(new File("sample.pdf")

// ドキュメントカタログを取得
PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog();
PDAcroForm acroForm = docCatalog.getAcroForm();
acroForm.setNeedAppearances(true);
acroForm.setXFA(null);
pdfDocument.getDocumentCatalog().setAcroForm(acroForm);

// 商用利用可能な日本語フォントを設定
// 拡張子otfは、サポートされてないみたいで動作しませんでしたので、拡張子はttfのフォントを推奨します。
PDFont font = PDType0Font.load(pdfDocument, new File("mplus-1p-regular.ttf"));

// PDFに出力する文字が日本語だとこの設定が必要
PDResources res = new PDResources();
COSName fontName = res.add(font);
acroForm.setDefaultResources(res);
acroForm.setDefaultAppearance('/' + fontName.getName() + " 10 Tf 0 g");

// 実際のPDFページ
// acroForm.getField（"オブジェクト名"）にAdobe Acrobatなどで、セットされているオブジェクト名を指定。
// field.setValueで値をセット。
// field.setReadOnly(true);で動的なフォームを読み込み専用に変換。
PDTextField field = (PDTextField) acroForm.getField("sample_field");
field.setValue("ここの文字が対象のfieldに出力されるよ！！");
field.setReadOnly(true);

// フロント側で描画するため、バイト配列で返却
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
pdfDocument.save(byteArrayOutputStream);
pdfDocument.close();

return byteArrayOutputStream.toByteArray();

```

## まとめ

英語かつ情報が古かったので隅から隅まで徹底的に調査しました。
スタックオーバーフローや英語のドキュメント、公式ドキュメントなど。。。
本来であれば一時情報である公式ドキュメントで解決したかったのですが、
情報が少なすぎました。。

特にこの箇所↓

```java
// PDFに出力する文字が日本語だとこの設定が必要
PDResources res = new PDResources();
COSName fontName = res.add(font);
acroForm.setDefaultResources(res);
acroForm.setDefaultAppearance('/' + fontName.getName() + " 10 Tf 0 g");
```

英語はエンジニアにとって必須だなぁと痛感した出来事でもありました。
また、僕も誰かの記事を見て救われたので、僕の誰かに役立つことを願って書き記します笑

最後まで見ていただきありがとうございます〜。LGTMよろしくです！

使用したフォント
https://fonts.google.com/specimen/M+PLUS+1p?subset=japanese

使用したライブラリ(バージョンは2.0.22を使用)
https://pdfbox.apache.org/

参考記事
https://qiita.com/ota-meshi/items/55a6c379544b33728b58
https://weblabo.oscasierra.net/java-pdfbox-1/


##
Tips: SQLでNullabeなカラムを条件式に加えるときは注意が必要

## これは何
SQLを書いているとき、Nullableなカラムを絞り込みや結合の条件式に使うことはよくあると思います。
Nullableなカラムを使うときは、ミスをしやすい気をつけないといけない点があるので、Tipsとして残します。

:::note
コメントでjnchitoさんから補足をいただきました
https://qiita.com/getty104/items/3c106fd976c4f6a8c5ac#comment-4eccca1a9834463e2eef
:::

## テーブルの例
今回の解説では、↓のようなテーブルを対象にクエリを描きます

- テーブル名: users
- certifiedカラム: 認証済みのユーザーかどうか
    - true → 認証済
    - false → 認証却下
    - NULL → 未認証

| id | certified |
|:-:|:-:|
| 1  | false |
| 2  | true |
| 3  | NULL |

## よくミスしてしまうパターン
認証済か、未認証のユーザーデータを取得することを想定し、以下のクエリを書きます。

```sql
SELECT *
FROM users
WHERE certified != false
```

一見あっていそうなクエリですが、
実はこのクエリでは正しいデータは取得できません。
なぜこのクエリでは意図したデータが取得できないかを開設します。

## NULLの挙動について
何が間違っているかを説明する前に、NULLの挙動について説明します。
NULLは比較演算子に使われると、基本的にNULLを返すという性質があります。
実際に以下のようなクエリを実行してみます。

```sql
SELECT (NULL != TRUE) IS NULL, (NULL OR TRUE) IS NULL, (NULL AND TRUE) IS NULL
```

すると結果は以下のようになりました

| col1 | col2 | col3 |
|:-:|:-:|:-:|
| true  | true  | true  |

つまり、NULLが条件式に使われた時点で結果はNULLになります。
また、絞り込みや結合の評価としてNULLが指定されると、それはfalseとして評価されます。

つまり、条件式にNULLが使われた時点で問答無用でFALSEになってしまいます。

## 何が間違っていたか
今回条件式に指定している`certified`は、Nullableで、今回は値がtrueのものと、NULLのものをとってくる必要がありました。それを意図して`certified != false`としていましたが、これでは値がNULLのデータは取得できない、ということになります。

正しくは、`IS NULL`演算子を使って、NULLであるものも取得することを明示する必要がありました。

```sql
SELECT *
FROM users
WHERE (certified = true) OR (certified IS NULL)
```

## 結論
Nullableなカラムを条件式に使う場合は、`IS NULL`を使う必要があるかどうか必ず考えるようにしましょう。
FlutterでiOSのソースを呼び出す

押したら文字が変わるだけのシンプルなものです。ただFlutterではなくiOSのソースを呼び出しています。画面は下記。
<img width="250" alt="Simulator Screen Shot - iPhone SE (3rd generation) - 2022-05-24 at 09.07.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/ef58c745-779a-60e6-01d9-60b710ba03b9.png">　<img width="250" alt="Simulator Screen Shot - iPhone SE (3rd generation) - 2022-05-24 at 09.07.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/32c65f28-072f-1268-33b0-225323501a82.png">

ソース(iOS)。コピペでOKです。

AppDelegate(ios/Runner/AppDelegate.swift)

    import UIKit
    import Flutter
    
    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate {
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
          GeneratedPluginRegistrant.register(with: self)
    
        let controller :FlutterViewController = window?.rootViewController as! FlutterViewController
          let methodChannel = FlutterMethodChannel(name: "test", binaryMessenger: controller as! FlutterBinaryMessenger)
    
          methodChannel.setMethodCallHandler({
            (call: FlutterMethodCall, result: FlutterResult) -> Void in
    
            if call.method == "getMessage" {
    
              result("Hello from iOS")
    
            } else {
              result(FlutterMethodNotImplemented)
            }
          })
    
          return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      }
    }


Flutter(lib//testView.dart)

testViewだけ作ってください。あとはコピペでOKです

    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
  
    class TestView extends StatefulWidget {
      const TestView({Key? key}) : super(key: key);
  
      @override
      _TestView createState() => _TestView();
  
      Widget build(BuildContext context) {
        // TODO: implement build
        throw UnimplementedError();
      }
    }
  
    class _TestView extends State<TestView> {
  
      final _channel = MethodChannel('test');
      String _message = 'Push Button';
  
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(''),
          ),
          body: Center(
            child: Column(
              children: <Widget>[
                Text(_message),
                ElevatedButton(
                  child: Text("ボタン"),
                  onPressed: () async {
                    final message = await _channel.invokeMethod('getMessage');
                    setState(() {
                      _message = message;
                    });
                  },
                ),
              ]
            ),
          ),
        );
      }
    }

FlutterでiOSのソースを読まないとできないような感じのことになり、調べたらわかりづらい記事ばかりで、イライラしたので自身の忘備録も兼ねて残しておきます。

誰かの参考になれば幸いです。
Python class 継承とオーバーライド

## 継承
BossクラスがEnemyクラスを継承しているので、Enemyクラスのメソッドが使える

```Python
class Enemy(object):

  def __init__(self, name):
    self.name = name

  def attack(self):
    print(self.name,"は攻撃した")

class Boss(Enemy):
  pass

enemy1 = Enemy("スライム")
enemy1.attack()
# スライムは攻撃した

boss = Boss("ボス")
boss.attack()
# ボスは攻撃した
```

## オーバーライド
EnemyクラスのattackメソッドをBossクラスで上書きする

```Python
class Enemy(object):

  def __init__(self, name):
    self.name = name

  def attack(self):
    print(self.name,"は攻撃した")

class Boss(Enemy):
  def attack(self):
    print(self.name,"は強い攻撃をした")

enemy1 = Enemy("スライム")
enemy1.attack()
# スライムは攻撃した

boss = Boss("ボス")
boss.attack()
# ボスは強い攻撃をした
```
【Rails】link_to で「ブラウザ上に表示する文字列」と「指定するURL」が同一のときは nil を使う。


## はじめに
未経験からエンジニアに転職しました。
まだまだわからないことだらけですが、毎日楽しく働いています！
業務や個人開発での発見やエラー解決などをアウトプットしています。
今回は、
##### link_to で「ブラウザ上に表示する文字列」と「指定するURL」が同一のときは nil を使う。
という内容です。
初学者向けの内容です。

# 結論
~~~ 
<%= link_to nil, 'https://qiita.com/' %>
~~~
上記のように書く。
下記と同じ結果になる。

~~~ 
<%= link_to 'https://qiita.com/', 'https://qiita.com/' %>
~~~


# 参考
https://github.com/rails/rails/blob/f33d52c95217212cbacc8d5e44b5a8e3cdc6f5b3/actionview/lib/action_view/routing_url_for.rb#:~:text=def%20url_for(options%20%3D%20nil)
AWS BenchPrepでラボが開けない

## 症状

AWS BenchPrepにてSOA(AWS認定 SysOps Administrator)の模擬問題をやろうとし、筆記は問題なく回答できたが、ラボを開こうとすると

Problem with lab
The firstName parameter is required.

と表示され、ラボが開けない


## 原因
名前が日本語で登録されていること
（ローマ字登録しないといけない）

## 対応
https://amazonwebservices.benchprep.com/
にログイン、右上のアイコンから「練習製品ポータル」を選択

左側のペインから「User Profile」を選択

Nameをローマ字で登録
（パスワードは入力不要）

Saveをクリック

右上のアイコンから「練習製品ポータル」を選択
SOA模試を選択し、ラボを開く。


## まとめ
AWS Summitの特典で模擬のクーポンをもらい、期限が短いのにラボが開かない・・・！と焦ってサポートへ連絡し、上記の方法を教えてもらいました。

お役に立ちましたら幸いです♪
[Power Platform] Power Platform ガバナンス入門（動画）

https://www.youtube.com/watch?v=XEeLmlVCxuU&list=WL&index=51
こちら公開されています（先日のWebinarの動画です）

Power Platform を一般ユーザーに開放するとやりたい放題されてしまう？と考える管理者は多いようです。一方で、市民開発者がアプリを作ってくれないとローコードソリューションを開放した意味がなくなってしまいます。
どのような制限ができるのか？制限しすぎるとどうなるのか？という疑問についてエンジニアがお答えします。
Python3 class書き方

## クラスの定義　３つのパターン

```Python
class Enemy:
```
```Python
class Enemy():
```
```Python
class Enemy(object):
```

## クラスの初期化

呼び出された時、初めに実行される
引数にself必須
```Python
class Enemy(object):
  
  # コンストラクタ
  def __init__(self):
    print("初期化") 

enemy1 = Enemy()
# 実行結果 ⇨ 初期化
```

### 何か値を保持させたい時
__init__に引数をつける
self.引数名 = 引数名

実体化するとき、クラスに引数を与える

```Python
class Enemy(object):

  def __init__(self, name):
    self.name = name
    print(name) 

enemy1 = Enemy("スライム")

# 実行結果 ⇨ スライム
```
## メソッド
引数にselfが必須
```Python
class Enemy(object):

  def __init__(self, name):
    self.name = name
    print(name)

  def attack(self):
    print(self.name,"は攻撃した")

enemy1 = Enemy("スライム")
enemy1.attack()

# 実行結果 ⇨　スライムは攻撃した
```
Chrome拡張機能の「OneTab」の使い方まとめ！【色分け/共有/保存場所】 | Aprico 

https://aprico-media.com/posts/4254

結構開きっぱなしでメモリをガンガン食っていたので
コレを導入していたのを思い出しましたっ

ファンネルを右クリック＞OneTab＞このタブをOneTabに送る

って運用すると良いかもっ＼(^o^)／
JavaScript　ページ遷移　location.href

## 用途
ページ遷移したい時に使う

## 方法
```js:
location.href = 'https://hoge.com/';
```
遷移させたいURLを代入します
パラメーターをつけることも可能です
例　`http://hoge.com?action=hoge&id=123`

```js:
location.href = '/hoge/hogehoge';
```
パス指定も可能です
パラメーターをつけることも可能です
例　`location.href = '/hoge/hogehoge?action=hoge&id=123';`

上記コードはどちらも、ブラウザの戻るボタンで前のページに戻れます
リネーム）大量のフォルダの中にある大量のファイル

大量のフォルダの中にファイルが入っていて、
すべてを一括でリネームしたいときに作りました。

この書き方が一番見やすくて、
いじりやすいと思います

~~~FinFrename.bat
for /D %%A in (*) do (
	cd "%%A"
	for %%B in (*.*) do (
		ren "%%B" "%%A_%%B"
	)
	cd ..
)
pause
~~~
Vim　閲覧専用モード

## 用途
vimで閲覧専用モードにしてファイルを開きたい時に使う

## 方法
下記の2つは同じ結果です
```
vim -R [ファイルパス]
```

`-R`
「閲覧専用モードで開く」というオプション

```
view [ファイルパス]
```

`view`
「閲覧専用モードで開く」というコマンド
「vim -R」がコマンドになった感じ。
STM32G031でアナログサーボ信号のモニター(ソフトウェアシリアル出力)


x 動作確認済み　2022/5/24 9:22


目的
アナログサーボ信号をモニターしたい。
既存のプログラムの使い回し


1 
2 VDD
3 GND
4 GPIO (したかったからした　特に指定なし)

8 SWD SWCLK
7 SWD SWDIO
6 デバッグ出力 9600bpsソフトウェアシリアル
5 PWM(IN) 400uS=0,2400uS=255


![o_con487.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/92bb5cec-8f81-f6e1-654d-005587958847.jpeg)


![o_con488.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d948c659-26a3-9db8-e7e7-21f40254a99a.jpeg)



送信　138 ( 1500us )を固定で送っている。　PWM_servo_test_031_P


https://qiita.com/caa45040/items/8c9b4ccbd59bd8f82d70





プログラム


```c++


//PWM_to_MON_031_1

#include <Arduino.h>

//10の割り算 0から1028までは、正しい。主に0から999
#define DIV10(n) ((n*205)>>11)

#define in_pwm   PA11 // 5pin

#define DW   digitalWrite
#define TX1        PA12  // 6pin
#define UART_DELAY 106   // 002-110 9600bps ok 031

//仮想シリアルへの一文字出力 9600bps
void pc_putc(char ch)
{
  DW(TX1, HIGH);

  DW(TX1, LOW);//START
  delayMicroseconds(UART_DELAY); //START BIT WAIT

  for (int ii = 0; ii < 8; ii++) {
    DW(TX1, (ch >> ii) & 1  );
    delayMicroseconds(UART_DELAY); //DATA 1-8BIT WAIT
  }//for

  DW(TX1, HIGH);//Stop
  delayMicroseconds(UART_DELAY); //StOP BIT WAIT

}//pc_putc


//文字列の表示
int pc_printf(char *str1) {

  //文字の中身がゼロか
  while (*str1) {

    //一文字出力
    pc_putc(*str1 ++);

  } //while

  //戻り値
  return (0);
}//pc_printf


//初期化
void setup() {

  delay(3000); //not Delete

  pinMode(in_pwm, INPUT); //pa11

  //TXポートの初期化
  pinMode(TX1, OUTPUT);
  DW(TX1, HIGH);

} //setup


//メインループ
void loop()
{
 
  //PWMでデータ取得
  int pwmco2=pulseIn(in_pwm,HIGH,2000000);

/*
  //データの表示 debug
  String thisString9 = String( pwmco2 );
  pc_printf( (char *)thisString9.c_str() );
  pc_printf( "\r\n" );
*/

  if(pwmco2 <= 400  ) { pwmco2 = 400; }
  if(pwmco2 >= 2400 ) { pwmco2 = 2400; }

  pwmco2 = pwmco2 - 400;
  
  int vel = (pwmco2 * 523) >> 12;
 
  //表示 debug
  //integer to String
  char out_buff[8];
  out_buff[3] = 0;
  out_buff[2] = '0' + (  vel - (DIV10(vel) * 10)  );  // '0'+(b%10)
  vel = DIV10(vel);                                   //  b/10
  out_buff[1] = '0' + (  vel - (DIV10(vel) * 10)  );  // '0'+(b%10)
  out_buff[0] = '0' +  DIV10(vel);                    // '0'+(s/10)

  //送信処理
  //send 8 byte
  pc_printf(out_buff);
  pc_printf("\r\n");

  //0.1秒の待ち
  delay(100); //←ここで送信間隔を調整する

} //loop


```
387 解答

# 参考
[Kevin Naughton Jr.](https://www.youtube.com/watch?v=St47WCbQa9M)
# 考え方
non repeating == unique と関連付ける。

unique -> Set or Map?　Set も Map　もunique　なものしか収納できないので便利。

この問題はindexを求めないといけないので、key(Character),value(Integer(Index))にしたほうが楽。
# 解答
```Java
	public int firstUniqChar(String s) {
		Map<Character, Integer> input = new HashMap<>();
		
		for (int i = 0; i < s.length(); i++) {
			char current = s.charAt(i);
			if (!input.containsKey(current)) {
				input.put(current, i);
			} else {
				input.put(current, -1);
			}
		}

		int min = Integer.MAX_VALUE;
		for (char c : input.keySet()) {
			if (input.get(c) != -1) {
				min = Math.min(input.get(c), min);
			}
		}
		
		return min == Integer.MAX_VALUE ? -1 : min;
		

	}
```
# 豆知識
## put 上書きできる
```Java
			if(map.containsKey(c)) {
				map.put(c, -1);
			}else {
				map.put(c, i);
			}
```
## これで一つずつ取得できる
```Java
		for(char c : map.keySet()) {
			if(map.get(c) != -1) {
				min = Math.min(map.get(c), min);
			}
		}
```

## ifの短縮
```Java
min == Integer.MAX_VALUE ? -1 : min;
```
画像からカラーパレット生成する

デザインで配色に悩む時、お洒落な鳥:bird:を眺めています。
その際に色を抽出できるとより参考になると考え、画像からカラーパレット生成に取り組んでみました。

![スクリーンショット 2022-05-24 5.33.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1116978/6330a0e3-2c41-0486-0083-ff61a30534bf.png)


## 使用技術
- [Vite](https://ja.vitejs.dev) : ホットリロードやビルドがとにかく速く開発が快適になる。
- [Vue3](https://v3.ja.vuejs.org/guide/migration/introduction.html) : Vue2からTypeScriptサポート充実したので開発しやすくなっている。
- [Firebase](https://firebase.google.com/?hl=ja) : ちょっとしたアプリ開発にもDBやサーバーレス関数など組み合わせられる。無料枠もあり非常にありがたい。
- [extract-colors](https://www.npmjs.com/package/extract-colors) : 今回の主役。画像からカラーパレット生成してくれる。

## extract-colorsを使ってみる
今回の主旨である「画像からカラーパレット生成」をやってくれます。
[README](https://github.com/Namide/extract-colors#readme)を参照しながらインストールします。

```
npm install --save extract-colors canvas
```
:::note warn
ブラウザ向けはextract-colorsのみのインストールが案内されていますが、私のVite環境ではcanvasも必要でした。
:::


使い方はシンプルでファイルへのパスや`ImageData`を渡すと、抽出された色が配列で得られます。
```typescript
import extractColors from 'extract-colors'

const src = 'my-image.jpg'

extractColors(src)
  .then((colors) => colors.forEach(console.log))
  .catch(console.error)
```

拙いですが型定義など加えて関数化したものです。
```typescript
import { extractColors } from "extract-colors";

export interface Color {
  hex: string;
  red: number;
  green: number;
  blue: number;
  area: number;
  saturation: number;
};

export const getImageColorAsync = async (
  filePath: string
): Promise<Color[]> => {
  try {
    const options = {
      pixels: 10000,
      distance: 0.2,
      saturationImportance: 0.2,
      splitPower: 10,
      colorValidator: (red: number, green: number, blue: number, alpha = 255) =>
        alpha > 250,
    };
    const colors = await extractColors(filePath, options);
    return colors;
  } catch (error) {
    console.warn(error);
    throw error;
  }
};
```

余談ですが[get-image-colors](https://www.npmjs.com/package/get-image-colors)という似たようなものもあります。
こちらは`require()`でのモジュールロードのみとなるのでご注意ください。

## Firebaseを連携させる
画像とカラーパレットの情報を保存できるようにします。
今回はFirebaseの提供するサービスのうち、FirestoreとStorageを使用しました。

- [Cloud Firestore](https://firebase.google.com/docs/firestore?hl=ja) : NoSQLデータベース。キー・バリュー形式でデータ格納する。[サポートされるデータ型](https://firebase.google.com/docs/firestore/manage-data/data-types?hl=ja)は要確認。
- [Cloud Storage for Firebase](https://firebase.google.com/docs/storage?hl=ja) : 画像、音声、動画、またはその他のユーザーが生成したコンテンツなどの保管に向いているバケット。

画像をStorageに保存して、画像パスとカラーパレットをFirestoreに保存する構成にしています。
![システム構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1116978/532baa5a-6fa1-e611-c1fa-b1db5335ce78.png)

Firestoreから得られるデータにTypeScriptを適用するために[FirestoreDataConverter](https://firebase.google.com/docs/reference/js/v8/firebase.firestore.FirestoreDataConverter)を加えると良いです。
また、timestampを加える際は、firestoreモジュールで提供されているものを使うとソート時の考慮が多少減るかと思います。
[firebase.firestore.Timestamp](https://firebase.google.com/docs/reference/js/v8/firebase.firestore.Timestamp)
```js
import { Timestamp } from "firebase/firestore";
const timestamp = Timestamp.now()
```

## まとめ
画像からカラーパレット生成のコア機能ができたので、chrome拡張と組み合わせて閲覧しているWebサイトのカラーパレット抽出など妄想膨らみますね...
ちなみに[Adobe Color](https://color.adobe.com/ja/create/image)というサイトで画像のテーマカラー抽出ができるので気になった方はそちら試してみてください。
POSTGRES の再帰処理の基本 ( WITH RECURSIVE )


# 準備

「データ的に木構造」なテーブルを作っておく
(RDBなのでもちろん、直接木構造のデータを作ることはできない)

```sql
DROP TABLE tree;

CREATE TABLE tree (
  id integer,
  parent integer
);
```

```sql
INSERT INTO tree
  (id, parent)
VALUES
  (1, null),
  (2, 1),
  (3, 1),
  (4, 3),
  (5, null),
  (6, 5),
  (7, 6),
  (8, 7)
;
```

# データの状態

```sql
SELECT * FROM tree;
 id | parent
----+--------
  1 |
  2 |      1
  3 |      1
  4 |      3
  5 |
  6 |      5
  7 |      6
  8 |      7
(8 rows)
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/0ee74610-b77b-5ecb-538c-235a19a93e42.png)

- 1は2と3を子に持つ
- 3は4を子に持つ
- 5から8まではまた別系統で、4世代分の親子関係を持つ

# クエリ例1

id 1のレコードと、id 1 を親に持つレコードを再帰的に得る。

```sql
WITH RECURSIVE r AS (
       SELECT * FROM tree WHERE id = 1
     UNION ALL
       SELECT tree.* FROM tree, r WHERE tree.parent = r.id
     )
SELECT * FROM r ORDER BY id;
```

### 結果

```sql
 id | parent
----+--------
  1 |
  2 |      1
  3 |      1
  4 |      3
```


id 1 のレコードを基準に、子の子までレコードをたどることが出来た。
1の直接の子ではない4も結果に含まれているのが分かる。


# クエリ例2

このデータの場合だと id 5 はもっと子の構造が深いが、それでも再帰的に結果を得ることが出来る。

```sql
WITH RECURSIVE r AS (
       SELECT * FROM tree WHERE id = 5
     UNION ALL
       SELECT tree.* FROM tree, r WHERE tree.parent = r.id
     )

SELECT * FROM r ORDER BY id;
```

```sql
 id | parent
----+--------
  5 |
  6 |      5
  7 |      6
  8 |      7
(4 rows)
```

# 参考

https://lets.postgresql.jp/documents/technical/with_recursive/1



<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
MySQL関連のエラー

5月度第3回講義で提供されたサンプルアプリをEC2にデプロイするまでに遭遇したエラーについて、自分なりの解釈と解決までの手段をメモ。

### エラーその１:認証パスワード有効期限切れ
```
Mysql2::Error: Your password has expired. To log in you must change it using a client that supports expired passwords.
```

Railsお抱えのMySQLクライアントからログインしようとする場合、初期パスワードは使用不可ということなんだろうか?
以下のコマンドでパスワードを変更し、これをdatabase.ymlに記述して解決した。
```
$ sudo mysql_secure_installation
```

### エラーその2:mysql.sockがない

```
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (２)
```
/tmpにmysql.sockがない(2)。
ググってみると、どうやら「ファイルがない」のが原因、つまりファイルを作ってしまえば良いとの情報が見つかった。

```
$ sudo touch /tmp/mysql.sock
```

これで解決すると思ったが、ダメだった。
```
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (13)
```

今度は(13)。

そもそもmysql.sockとは何者か。
どうやらMySQLクライアントとサーバーが通信するときに使うパイプ役のファイル？？？みたいなものらしい。
つまり、mysql.sockファイルの在り処の認識が、クライアントとサーバーとで一致してなければならないと。

探してみると、このファイルは/var/lib/mysql/にあった。
一方、database.ymlを見てみると、/tmp/mysql.sockとなっている。
クライアントとサーバーとで、別の場所を探しに行ってしまっているのが原因。database.ymlを修正し、解決。

### エラーその３:データベースがない
データベース作ればいいだけ。



ーーー
というわけで、無事デプロイ、起動確認。
ただ繋ぐだけでも結構大変。きちんと理解できてれば他人の役に立つことも書けるだろうけど、今の自分にはとても無理。
脱初心者の壁、高くない…？