OmniAICreator/Qiita-1.07M huggingface dataset:
カーネルのバージョンを確認する

# はじめに

- Linuxにおけるハードウェアやカーネル、OSに関する情報を確認する手段はいくつかあり、毎回調べるのも面倒なのでまとめておく

# unameコマンドで確認

- ハードウェア、カーネル、OS等の情報を幅広く取得できるコマンド
- `uname`はUNIX NAMEが由来だと言われている

```bash
# ハードウェア名の表示
$ uname -m
x86_64

# CPUの種類の表示
$ uname -p
x86_64

# ハードウェアプラットフォームの表示
$ uname -i
x86_64

# カーネル名の表示
$ uname
Linux

# カーネル名の表示(オプション無しの動作と同様)
$ uname -s
Linux

# OS名の表示
$ uname -o
GNU/Linux

# カーネルのリリース番号の表示
# 5.13 ... カーネルのバージョン
# 52 ... ABI(Application Binary Interface)が変更された回数
# generic ... UbuntuのFlavourの1つ
# Flavourはカーネルのオプションをひとまとめにした概念で、いくつかの種類が用意されている
# genericはデスクトップ用途、serverはサーバ用途等
# 参考: https://wiki.ubuntu.com/Kernel/Dev/Flavours
$ uname -r
5.13.0-52-generic

# カーネルのバージョンの表示
# 59 ... アップロード回数
# 日付はリリースされた日付
$ uname -v
#59-Ubuntu SMP Wed Jun 15 20:17:13 UTC 2022

# ホスト名の表示
$ uname -n
hoge

# ホスト名の表示
$ hostname
hoge

# 全ての情報の表示
$ uname -a
Linux hoge 5.13.0-52-generic #59-Ubuntu SMP Wed Jun 15 20:17:13 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
```

# /etc/os-releaseの確認

- OSの情報
- `/etc/os-release`はDebian系でもRed Hat系でも確認できる模様

```bash
# Ubuntuの場合
$ cat /etc/os-release 
PRETTY_NAME="Ubuntu 21.10"
NAME="Ubuntu"
VERSION_ID="21.10"
VERSION="21.10 (Impish Indri)"
VERSION_CODENAME=impish
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=impish

# CentOSの場合
$ cat /etc/os-release
NAME="CentOS Linux"
VERSION="8"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Linux 8"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-8"
CENTOS_MANTISBT_PROJECT_VERSION="8"
```

# /etc/lsb-releaseの確認

- Debian系のOSの情報

```bash
# Debian系のバージョンの表示
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=21.10
DISTRIB_CODENAME=impish
DISTRIB_DESCRIPTION="Ubuntu 21.10"
```

# /etc/redhat-releaseの確認

- Red Hat系のOSの情報

```bash
# Red Hat系のバージョンの表示
$ cat /etc/redhat-release
CentOS Linux release 8.4.2105
```

# lsb_releaseコマンドで確認

- LSBはLinux Standard Baseの略
    - ディストリビューション間の相互運用性を高めるために一部の仕様の標準を定めた規格
- `lsb_release`コマンドの利用には追加で`lsb-core`のインストールが必要

```bash
$ lsb_release
LSB Version:	core-11.1.0ubuntu3-noarch:security-11.1.0ubuntu3-noarch

# すべての情報を表示
$ lsb_release  -a
LSB Version:	core-11.1.0ubuntu3-noarch:security-11.1.0ubuntu3-noarch
Distributor ID:	Ubuntu
Description:	Ubuntu 21.10
Release:	21.10
Codename:	impish
```
M1MacでDockerが起動しない問題の対処方法

# Macのターミナル上でDockerコマンドが起動しない

## 背景

GitからサンプルコードをCloneしてきて、dockerを起動しようとしたところ以下のエラーメッセージが

buildコマンド
```
docker image build -t hoge:latest .
```
エラーメッセージ
```
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

## 解決

デスクトップからDocker Desktop(以下の画像のアプリケーション)を起動することで解決した。
ダブルクリックして起動が確認した時点で、他の操作は不要だった。

![スクリーンショット 2022-07-05 15.59.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599414/83622288-1031-6633-2f54-5333b504a074.png)


buildの成功例
```
docker image build -t instabot:latest .
[+] Building 118.6s (11/11) FINISHED                 
```


### Dockerのインストール

Docker Desktopのインストール自体はこちらから。
https://www.docker.com/products/docker-desktop/



### 参考

https://www.konosumi.net/entry/2018/01/21/125523
【備忘録】Unity ML-Agentsで学習開始する方法とTensorBoardで結果を見るまでの流れ

### 【学習の準備と流れ】

**1. 学習用スクリプトとyamlファイルを作成．**
AgentのコンポーネントのBehavior ParametersのBehavior Nameを固有のものに変更しておく．
そのほか，AgentのコンポーネントのSpace SizeやContinuous Actions，Interface Deviceなど必要なパラメータをセットしておく．

<b>※yamlの2行目はAgentのコンポーネント「Behavior Parameters」の一番上のBehavior Nameと一致させる必要あり．</b>
ここが一致していないと以下のようなエラーが出る

````
mlagents.trainers.exception.TrainerConfigError: The behavior name PivotAgent_xy_smooth has not been specified in the trainer configuration. 
Please add an entry in the configuration file for PivotAgent_xy_smooth, or set default_settings.
````

<br/ >
yamlファイルの例
```yaml:board_config.yaml
behaviors:
  BoardBehavior:
    trainer_type: ppo
    hyperparameters:
      batch_size: 10
      buffer_size: 100
      learning_rate: 3.0e-4
      beta: 5.0e-4
      epsilon: 0.2
      lambd: 0.99
      num_epoch: 3
      learning_rate_schedule: linear
    network_settings:
      normalize: false
      hidden_units: 128
      num_layers: 2
    reward_signals:
      extrinsic:
        gamma: 0.99
        strength: 1.0
    max_steps: 500000
    time_horizon: 64
    summary_freq: 10000
```


**2. Winwdows PowerShellでanaconda起動．必要であればUnityのプロジェクトがある場所までフォルダ移動しておく.**
(base) PS C:\Users\Mlab> `conda activate ml-agents`

**3. 1.で作成したyamlファイル(のパス)を指定して学習開始．run-id=の後ろ(ここでは"RollerBall616")が出力フォルダとなる（固有名である必要あり）．**
(base) PS C:\Users\Mlab> `mlagents-learn config/board_config.yaml --run-id=RollerBall616`

**4. PowerShell上にUnityのロゴが出て，エラーがなければOK．Unity Editorで再生ボタンを押して学習開始．**
   yamlに記述したハイパーパラメータなどの情報が正しく表示されればOK．学習が進むにつれエピソード数や経過時間などが更新されていく．
![PowerShell_UnityLogo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/6d673e33-f6c1-0631-a826-8fb4bd03a7a6.jpeg)
Unityのロゴというのはこんな感じ↑

---


### 【TensorBoardで結果を見る】

**1. anaconda起動**
(base) PS C:\Users\Mlab> `conda activate ml-agents`

**2. resultsフォルダに移動**
(ml-agents) PS C:\Users\Mlab> `cd results`

**3. ログファイルのセット**
(ml-agents) PS C:\Users\Mlab\results> `tensorboard --logdir=./RollerBall616 --port=6006`

**出力**
TensorFlow installation not found - running with reduced feature set.
Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
TensorBoard 2.8.0 at http://localhost:6006/ (Press CTRL+C to quit)

ブラウザで↑のURLにアクセスすれば良い．
FlutterでiOSシュミレーターが作動しない問題

久々に修正しようとflutterを立ち上げてiosシュミレーターを開こうとしたら、デバッグコンソールに下記エラーが出て立ち上がらなくなっていました。
```
Running "flutter pub get" in hogehoge...
The current Dart SDK version is 2.17.0-182.0.dev.

Because flutter_hooks 0.18.5+1 requires SDK version >=2.17.0 <3.0.0 and no versions of flutter_hooks match >0.18.5+1 <0.19.0, flutter_hooks ^0.18.5+1 is forbidden.
So, because hoge depends on flutter_hooks ^0.18.5+1, version solving failed.
pub get failed (1; So, because hoge depends on flutter_hooks ^0.18.5+1, version solving failed.)
Exited (1)
```
動かしているシュミレーターなどを一度止めてflutterを安定バージョンにしてから、
```
flutter channel stable
```
アップグレードしたら。。。
```
flutter upgrade
```
下記エラーが出てきたので、
```
Running "flutter pub get" in hogehoge...
This app is using a deprecated version of the Android embedding.
To avoid unexpected runtime failures, or future build failures, try to migrate this app to the V2 embedding.
Take a look at the docs for migrating an app: https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects
The plugin `audioplayers_android` requires your app to be migrated to the Android embedding v2. Follow the steps on https://flutter.dev/go/android-project-migration and re-run this command.
Exited (1)
```
androidフォルダ削除後に
```
flutter run
```
してみると、
```
Error: CocoaPods's specs repository is too out-of-date to satisfy dependencies.
To update the CocoaPods specs, run:
  pod repo update



Error running pod install
Error launching application on iPhone SE (3rd generation).
```

```
cd ios
```

```
pod repo update
```
`Updating spec repo 'trunk'`と出た後、再度ディレクトリを戻して
```
flutter run
```
するが、![スクリーンショット 2022-07-05 9.49.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/7c89e113-0967-d242-5634-b589a6ceef8a.png)
ローディングが永遠と終わらなかったので、一旦解除してiosフォルダから直接
```
cd ios
pod install
```
を試みる。。。
![スクリーンショット 2022-07-05 9.54.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/d6aefbcd-ccb8-7860-becc-8e3ac216d998.png)
ここで時間がかかっているようなので正常にはインストールできているようです。

終了したので`F5`で実行してみたが、新しいエラーが。。。
```
Umbrella header for module 'GoogleUtilities' does not include header 'GULSwizzler.h'
```
すかさず下記コマンドを試みる。(DerivedDataのキャッシュをクリア)
```
rm -rf ~/Library/Developer/Xcode/DerivedData/
cd ios
pod deintegrate
pod update
```
エラー内容変わらず。。。
```
Error launching application on iPhone
```
このエラーも出ていたので、そちらから対応してみるiosフォルダにいる状態で
```
pod install --repo-update 
flutter clean
flutter pub get
flutter pub upgrade
```
```
rm -Rf ios/Podfile
rm -Rf ios/Podfile.lock
```
`Podfile, Podfile.lock, Podsフォルダ`を削除してから
```
flutter clean
```
して実行しても変わらず。
```
rm -Rf ios/Pods
rm -Rf ios/.symlinks
rm -Rf ios/Flutter/Flutter.framework
rm -Rf ios/Flutter/Flutter.podspec
rm ios/Podfile
```
もう一度削除して、
```
flutter upgrade
cd ios
pod init     // <---errorが出なかったらupdateへ
pod update
flutter clean
```
してから
```
flutter pub get
flutter run
```
したらいけましたヽ(´o｀；　いったいなにが問題だったのか。。。
iosフォルダ内の`project.pbxproj` `Podfile` `Podfile.lock` と`pubspec.lock`の書き換えが必要だったようですが、それでも解決できない場合は実装に問題があるのかと。
STM32L010とMCP9701で温度をシリアルに出力 (RawSerial)(調整しやすくした)


x MCP9701-E/TO 販売コード 103199

x Mbed2のリビジョンは、143
x あまり正確では、ない

目的
秋月で売っている安価なMCP9701(約25円)を使って温度を出力する。

A0は、PA_0の事

![o_con562.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/bee48e27-6e2e-cbae-eb35-38be8e7eb174.jpeg)




```c++


//SER_MCP9701_DEC_010_1

//温度

#include "mbed.h"

//1000の割り算 だいたい正しい。
#define DIV1000(n) ((n+((n*25)>>10))>>10)

//10の割り算 0から9999までは、正しい。
#define DIV10(n) (((n*409)+((n*154)>>8))>>12)

//アナログ入力の設定
AnalogIn adc_vbat(A0);

RawSerial pc(PA_2, PA_3); //010

//メイン関数
int main() {

    int  s;        //ADCの値
    int  v;        //電圧
    int  t;        //温度
    char data1[]={0,0,0}; //バッファ
    char data2[]={0,0,0}; //バッファ


    //無限ループ
    while(1) {

        //ADCの読み込み 0から4096
        s = (adc_vbat.read_u16()>>4);

        //センサーのADC値を電圧に変換 ex (4096*3300)/4096=3300
        v = (s * 3300)>>12;

        //センサーの電圧を温度に変換 20.1を10倍した物　201
        //400mVは、0℃の位置 400
        //19.5mVは、温度計数 195   係数は、約512
        t = DIV1000((v - 400) * (100000 / 195));

        //温度を整数と小数に分ける
        data2[0]='0'+ (t-(DIV10(t)*10)); //t%10
        t = DIV10(t);                    //t/10

        //温度の表示
        data1[0]='0'+ DIV10(t);           //t/10
        data1[1]='0'+ (t-(DIV10(t)*10));  //t%10
        pc.printf(data1);  //整数
        pc.printf(".");    //小数点
        pc.printf(data2);  //小数点以下
        pc.printf("\r\n"); //リターン

        //1秒の待ち
        wait_ms(1000);

    } //while

} //main

//容量削減
void error(const char* format, ...){}


```
coilライブラリのモノクロ機能の代替実装

# 初めに
今回は、`Android`実装でよく使われている画像読み込みライブラリの一つである`coil`からモノクロで描画する機能が削除されるとのことで、代替実装を備忘録ついでに残しておこうと思います。
### 本文
まず、元々`coil`で使われていたモノクロ機能のコードは下記のurlに飛んでもらえれば確認できます。
https://github.com/coil-kt/coil/blob/1.4.0/coil-base/src/main/java/coil/transform/GrayscaleTransformation.kt
`coil`側はこれを基に自分たちで実装してくれれば、画像の加工するための機能自体は決してないから問題なく実装できると言っています。
- equals
- hashCode
- toString
上記三点は先述したurlにある元のコードと何も変わりませんが、他の部分でエラー3箇所出ると思います。
まず、元々は`coil`側で実装されていた`key`が`cacheKey`という名前に変更されています。
次に`transform`の引数に変更があります。
最後に`input.safeConfig`で***Unresolved reference: safeConfig***になるかと思います。
以上、3つの理由によりエラーが発生してしまいます。
逆にそこさえ直してしまえば何の問題もなくこれまで通り利用することができるということです。
### コード
実際に動くコードとしては、以下になります。
```kotlin
class GrayscaleTransformation : Transformation {
    override val cacheKey: String
        get() = javaClass.name

    override fun equals(other: Any?) = other is GrayscaleTransformation

    override fun hashCode() = javaClass.hashCode()

    override fun toString() = "GrayscaleTransformation()"
    override suspend fun transform(input: Bitmap, size: Size): Bitmap {
        val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)
        paint.colorFilter = COLOR_FILTER
        val output = createBitmap(input.width, input.height, input.config)
        output.applyCanvas {
            drawBitmap(input, 0f, 0f, paint)
        }

        return output
    }

    private companion object {
        val COLOR_FILTER = ColorMatrixColorFilter(ColorMatrix().apply { setSaturation(0f) })
    }
}
```
`key`に関しては名前を変更するだけなので簡単だとは思います。
`transform`に関しては不要になった引数を削除し、代わりに`createBitmap`を使ってあげます。
`input.safeConfig`も修正方法はすごく簡単で代わりに`input.config`を使うだけでエラーは解消されます。
### 最後に
ただurlを基にコピペするだけではないので、備忘録＆メモ帳くらいの感覚で記事にさせていただきました。
`coil`は本当によく使うライブラリなので、今後の自分のためにもなると思いますし、皆さんのお役に立てれば光栄です。
OracleのINDEXについて学びがあったので一旦雑に記録しておく（更新予定アリ）

※とりあえず更新するつもりだが忘れないうちに書いておく。

エンジニア歴８年目だが、Oracleのindexで新しいことを学んだので記録しておく。
なお内容は至極基本的なもののはずなので目新しいことを求めて来た方は、ブラウザバックでお願いします。。

逆に若手エンジニアの皆さん。エンジニアなんてこんなもんなんで、**無知だから勉強しなきゃ**はOKですけど、 **こんな事も知らないとか私ダサいのでは？** とか思う必要ありません。
**「聞くは一瞬の恥、聞かぬは一生の恥」**。地道に知識を増やせばいいんです。
そして、必要になったときに必要なものを学べばよいのです。
取り急ぎ使わない上に役にも立たない知識を最初から学ぶのは工数がもったいないです。
（物理学科の学生が試験前に法律の勉強しないよね？すればいつかは役に立つかもだけど。そういうこと。あえてやる必要はない。と思っている。）

脱線しましたが本題へ。

# INDEXてなに？のまえにKeyについて

RDBではPKとINDEXという大きく２つのものでデータの一意制を担保している。
（ER図出来にはOUTER_KEYとかもあるんでしょうけど一旦割愛）

PKは **P**rimary **K**eyの略で、文字通りこのカラムが一意になるようなデータしか保存できないというもの


例）employeeテーブルにid、name、sectionと言うかラムが存在し、idがPKの場合

```
|id(PK)    |name      |section   |
|----------|----------|----------|
|1         |TANAKA    |JINJI     |
|2         |SUZUKI    |SOUMU     |
|3         |TAKAHASHI |IT        |

```
こういうデータに対し

```SQL
INSERT INTO EMPLOYEE (id,name,section) VALUES (1,'TAKANKA','JINJI')

```
を実行すると **一意制約違反** で失敗する。

```SQL
INSERT INTO EMPLOYEE (id,name,section) VALUES (4,'TAKANKA','JINJI')

```
を実行するとinsertされて、
```
|id(PK)    |name      |section   |
|----------|----------|----------|
|1         |TANAKA    |JINJI     |
|2         |SUZUKI    |SOUMU     |
|3         |TAKAHASHI |IT        |
|4         |TANAKA    |JINJI     |
```
となる。

データの一意性を担保するためのKeyがPKの役割。


# じゃあINDEXてなに？

まずここに良さげな記事があるので貼っておきます。

https://qiita.com/justaway08/items/94f04d1e13959ebb0a98

この章が学んだ内容。（今後まともな状態に更新かけるつもり。つ・も・り！）

私の浅はかな考えでは今まで　**SELECT文が速くなる。それは実行計画を作るときにINDEXがあると効率のいい実行計画になるからだ**程度のことしか知らなかったが、
ORACLEでは（ほかは未調査）INDEXを貼った上で、**UNIQUENES**というものの設定ができ、

- UNIQUE
- NONUNIQUE

の2種類の設定ができるんだと。

- UNIQUE

になっていると実質PKと同じような役割になると。
つまりPKだけではなく **INDEX** の **UNIQUENES** も確認しないと、一意制約違反の本当の理由はわからないかもね。か・も・ね。

以上。
CancelablePromise を自前で作るのはやめておいたほうがいいのでは

世の JavaScript エンジニアは一度は考えることではないかと思うけども。

JavaScript の Promise には処理を途中でキャンセルする API は無いので、キャンセルできるようにする Promise を考えた。

``` js
class CancelablePromise extends Promise {
    #reject = null

    constructor(executor) {
        let _reject = undefined
        super((resolve, reject) => {
            _reject = reject
            return executor(resolve, reject)
        })
        this.#reject = _reject
    }

    cancel(reason) {
        this.#reject(reason)
    }
}
```

普通の Promise に `cancel` メソッドを生やして、外部からでも呼べるようにした。

``` js
const promise = new CancelablePromise((resolve, reject) => { /* 非同期処理 */ })

// キャンセルする
promise.cancel()
```

動かしてみると、一見ちゃんと動いているように見える。

しかし、
よくみると処理そのものは止まっていない。

例えばこういう非同期関数を用意する。

``` js
// 10秒後に resolve する非同期関数
function wait10sec() {
  return new CancelablePromise((resolve, reject) => {
    let timer = 10 + 1
    const id = window.setInterval(() => {
      console.log(--timer)
      if (timer === 0) {
        window.clearInterval(id)
        resolve()
      }
    }, 1000)
  })
}
```

10秒後に完了する非同期関数を実行して、5秒後にキャンセルしてみる。

``` js
const promise = wait10sec()
  .then(() => console.log("Yay"))
  .catch(() => console.log("Oops"))

// 5秒後にキャンセルする
window.setTimeout(() => promise.cancel(), 5000)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/9414ccc3-c6b8-44f7-b7aa-f2e3f08eec1c.png)

全然止まってない上に `then` にチェーンされとるやんけ！！

つまり Promise のステータスが rejected になるだけで、非同期処理そのものを停止できるわけではない、と。(then にチェーンされたのは何故なのか不明)

一度実行した非同期処理を止めるのは無理では？と思っているのですがどうなのでしょうかね。
有識者の方はコメントいただけるとありがたいです。
MicroModalでモーダル閉じても親ウィンドウにフォーカスが戻らない場合


JSでcloseメソッド呼んでいる場合、繰り返し実行するとbodyに「overflow: hidden」が残ってしまうことがある。

`MicroModal.close(trigger)`
`$("body").attr("stryle","")`

とりあえず閉じたら毎回、無理矢理スタイル消してみたけど。場当たり的だな
Windowsバッチでよく使う処理一覧

## はじめに
この記事はWindowsバッチを書く時によく出てくる処理について一覧にしたものです。個人的な備忘録メモですが、皆様のお役にも立てたら嬉しく思います。

## 処理一覧
#### コマンド実行時の標準出力をOFFにする
```bat
@echo off
echo 明示的なechoは出力されます。
```
バッチファイルの先頭には必ずつけよう。

#### バッチファイルの置かれたパスを取得する
``` bat
rem バッチファイルの置かれたパスを取得する
set BATCH_PATH=%~dp0
```

#### 現在のパスを取得する
```bat
rem 現在のパス取得
cd C:\tmp\mybatch_tmp
set CURRENT_PATH=%CD%
```

#### コマンド実行のエラーハンドリング1
```bat
git pull
if %errorlevel% neq 0 ( goto ERROR )

:SUCCESS
echo Processing Success.
goto FINAL
:ERROR
echo Processing Error !!
:FINAL
echo Finish BAT Program.
```
コマンドは何でもよいが、git pullを例にした。

#### コマンド実行のエラーハンドリング2
```bat
call ant "compile" -f build.xml -l compile.log
if %errorlevel% neq 0 ( goto ERROR ) 
```
コマンドによってはcallをつける必要がある。エラーハンドリングした後の処理は前述の通り。

## とりあえず、ここまで。
マウスを使わない開発環境をつくるための色々

# マウスを使うのが鬱陶しい!
キーボードとマウスの間を右手が行ったり来たりするのは、鬱陶しいものです。
純粋にタイムロスになりますし、なによりホームポジションが崩れてしまうのが致命的です。

__ならば、いっそ無くしてしまいましょう__

ここでは、私がマウスをデスクから消し去るためにやっていることをいくつかご紹介します。

## 私の環境
- OS: Windows11
- PC: Lenovo thinkpad
- エディタ: VSCode(拡張機能でVimを入れています)
- キーボード配列: 日本語配列
あとはフリーソフトのAutoHotKey(詳しくは後述)を入れています。

## ショートカットを使う
真っ先に思いつくのがこれだと思います。VSCodeのショートカット紹介は何番煎じか分からないくらいですが、私が使っている便利なショートカットを紹介します。Windowsのショートカットも合わせて紹介します。

(ショートカットのごく一部を紹介します。もっと知りたい方は以下を参考にしてください。)

[Windowsショートカットキー一覧](https://dekiru.net/article/18619/)

[キーボードから手を離さずにVS Codeで開発したいという気持ちを大切にしています - 10bace LOG](https://insider.10bace.com/2019/02/22/vs-code%E3%81%A8%E3%81%8B%E3%81%AE%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88%E3%81%AE%E3%81%AF%E3%81%AA%E3%81%97/)
↑個人的にめちゃめちゃ参考にさせてもらっている記事です

### alt + tab (Windows)
アプリの切り替えが出来ます。
例えば、エディタからブラウザへ切り替えるときに、一瞬で切り替えることが出来ます。
デバックの際はエディタとブラウザを行き来するので重宝しますし、開発でない普段使いでも使えるショートカットです。
便利な割には認知度が低いんじゃないでしょうか？気のせい？

### win + 数字 (Windows)
タスクバーのアプリを起動します。左から順番に1、2、3...と番号が振られていて、win + 1 を押すとタスクバーの一番左のアプリが起動します。エディタなどよく使うアプリを左側におくと楽に起動できます。
ちなみにエクスプローラを左側に置く必要はありません。__win + e__ で起動できるからです。

### ctrl + 数字 (VSCode)
大体の人は画面を左右に分割して作業をしていると思います。必然的に画面の左右を行き来する場面が出てくると思います。ctrl + 1を押せば左の画面に移動でき、ctrl + 2を押せば右の画面に切り替わります。(2画面分割の場合)

### ctrl + p (VSCode)
コマンドパレットを起動します。ファイルを開くときにエクスプローラからカチカチクリックしてファイルを探すのは面倒です。ctrl + pを押して、ファイル名を入力してEnter。これで狙ったファイルを起動できます。

### crtl + @ (VSCode)
ターミナルの表示・非表示を切り替えます。ターミナルを頻繁に使う人には嬉しいショートカットです。

## Vimを使う
Vimの概要については割愛しますが、Vimを使えばデスクからマウスが駆逐されます。それどころか矢印キーも要らなくなります。ただVimは操作があまりにも変態的なので、万人におすすめはできません。
マウスに親を殺されたか何かで、マウスを抹殺しないと気がすまない人はVimを使いましょう。

Vimのインストールや操作に関しては山ほど記事がありますので、そちらを参考にしてください。
VSCodeの拡張機能でVim(Vimのキーバインド)があります。使用法は以下の記事を参考にしてください。
[VSCodeで始めるVim](https://qiita.com/jintz/items/d357478271179c90ffab)

## AutoHotKeyを使う
AutoHotKeyはフリーソフトで、自分の好き勝手にショートカットを登録することが出来ます。
使い方などは山ほど記事がありますので、そちらをご参考に。
[AutoHotKey公式](https://www.autohotkey.com/)

私の場合、無変換 + hjkl を上下左右移動に割り当てています。これでVimライクな操作をあらゆる場所で使えるようになります。
あとは変換キーを半角/全角に割り当てています。これをすることで、親指で半角/全角の切り替えができます。

ところで半角/全角キーってなんであんなに遠い場所にあるんですかね？ﾜｹｶﾞﾜｶﾗﾅｲﾖ

## トラックポイント
これはハードウェアの話になりますので、実際にやるのは難しいと思います。もしプログラミング用にこれからpcを新調する、という方がいましたら、Lenovoのthinkpadをオススメさせてください。

thinkpadにはキーボードの真ん中に丸い出っ張りがついています。こいつをグリグリ動かせばマウスカーソルが動きます。ホームポジションを崩さずにマウス操作が出来る革命的なデバイスです。

## まとめ
マウスを使わないようにするための色々を紹介しました。私の環境に依存している部分が多かったり、好みがかなり出てしまっていますので、そのあたりはご了承下さい。自分なりに方法を模索する際に、この記事が参考になれば幸いです。

私はプログラミング初学者ですが、コーディング速度を上げることの大切さを実感しています。コーディング速度を上げれば、同じ時間でも学べる量が変わってきますし、操作に取られる手間が減った分、考えることに割ける時間が増えます。

デスクからマウスを排除して、爆速コーディングを目指しましょう!
aptコマンドで指定のパッケージのみアップグレードする

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. apt のアップグレードで指定のパッケージのみアップグレードしたい！

`apt update`して、アップグレードできるパッケージを`apt list --upgradable`で確認しました。

(下記一例)
```io
$ apt list --upgradable
Listing... Done
linux-aws/jammy-updates 5.15.0.1014.14 amd64 [upgradable from: 5.15.0.1013.13]
linux-headers-aws/jammy-updates 5.15.0.1014.14 amd64 [upgradable from: 5.15.0.1013.13]
linux-image-aws/jammy-updates 5.15.0.1014.14 amd64 [upgradable from: 5.15.0.1013.13]
mesa-va-drivers/jammy-updates 22.0.1-1ubuntu2.1 amd64 [upgradable from: 22.0.1-1ubuntu2]
mesa-vdpau-drivers/jammy-updates 22.0.1-1ubuntu2.1 amd64 [upgradable from: 22.0.1-1ubuntu2]
mesa-vulkan-drivers/jammy-updates 22.0.1-1ubuntu2.1 amd64 [upgradable from: 22.0.1-1ubuntu2]
nginx/stable 1.22.0-1~jammy amd64 [upgradable from: 1.20.2-1~jammy]
php7.4-apcu/jammy 5.1.21+4.0.11-8+ubuntu22.04.1+deb.sury.org+1 amd64 [upgradable from: 5.1.21+4.0.11-7+ubuntu22.04.1+deb.sury.org+1]
php7.4-cli/jammy 1:7.4.30-3+ubuntu22.04.1+deb.sury.org+1 amd64 [upgradable from: 1:7.4.29-2+ubuntu22.04.1+deb.sury.org+1]
php7.4-common/jammy 1:7.4.30-3+ubuntu22.04.1+deb.sury.org+1 amd64 [upgradable from: 1:7.4.29-2+ubuntu22.04.1+deb.sury.org+1]
php7.4-json/jammy 1:7.4.30-3+ubuntu22.04.1+deb.sury.org+1 amd64 [upgradable from: 1:7.4.29-2+ubuntu22.04.1+deb.sury.org+1]
php7.4-opcache/jammy 1:7.4.30-3+ubuntu22.04.1+deb.sury.org+1 amd64 [upgradable from: 1:7.4.29-2+ubuntu22.04.1+deb.sury.org+1]
php7.4-phpdbg/jammy 1:7.4.30-3+ubuntu22.04.1+deb.sury.org+1 amd64 [upgradable from: 1:7.4.29-2+ubuntu22.04.1+deb.sury.org+1]
php7.4-readline/jammy 1:7.4.30-3+ubuntu22.04.1+deb.sury.org+1 amd64 [upgradable from: 1:7.4.29-2+ubuntu22.04.1+deb.sury.org+1]
```

この中で、nginxやphp7.4だけアップデートして他のはアップデートしたくないということがあります。

Redhat EL系であれば、`yum update php7.4*` といったワイルドカードでの特定のパッケージのみアップデートすることが可能です。
しかし、apt コマンドの場合は、`apt upgrade php7.4*`という指定をすることができません。

そこで、やり方を調べました。

# 1. aptコマンドで指定のパッケージのみアップグレードする方法

以下のように指定する

```bash
sudo apt install --only-upgrade php7.4*
```

# 2. 参考

How to upgrade a single package using apt-get? - Ask Ubuntu
https://askubuntu.com/questions/44122/how-to-upgrade-a-single-package-using-apt-get
PlayCanvasのエンティティ内のスクリプトの実行順序について

PlayCanvas Editorで開発をしている際のスクリプトの実行順序についてinitializeとpostInitializeの実行順序についてまとめました。


![スクリーンショット 2022-07-05 14.27.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/b7554ca9-d486-0862-cd2d-8f4a7f9f9f97.png)

ヒエラルキー内の各エンティティにinitializeが呼び出された際にエンティティ名を出力するスクリプトを追加します。

```javascript
var Script1 = pc.createScript('script1');
Script1.prototype.initialize = function () {
    console.log(this.entity.name);
};
```

```javascript
var Script2 = pc.createScript('script2');
Script2.prototype.initialize = function () {
    console.log(`${this.entity.name} - 2`);
};
```
コンソールに出力をするとこのようになります。このようにエディタを利用してスクリプトを設定している場合の読み込み順序はヒエラルキーの上から読みこまれます。また、スクリプトも並び順の通りで呼び出されます。

![スクリーンショット 2022-07-05 14.24.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/24c38114-8b57-213c-92b2-2d46c0609bc7.png)


### エンティティの子エンティティを追加した場合
先程のシーンのBoxエンティティの子要素としてCapsuleを追加しました。
子のエンティティにも同様にスクリプトを追加します。

![スクリーンショット 2022-07-05 14.32.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/b9b19b18-207f-3fbf-5eda-9c72565eac5a.png)

実行結果はこちらです。この場合もヒエラルキーの上から実行され、スクリプトの順序で実行されることは変わりませんが、親エンティティ　→　子エンティティの順でスクリプトが実行されます。
![スクリーンショット 2022-07-05 14.29.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/3399c8ed-bebd-9399-0ba3-61334dff918d.png)


### postInitializeについて

![スクリーンショット 2022-07-05 14.34.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/37f225a7-4c67-7a68-337f-26d71450dba4.png)

postInitializeが実行された際にコンソールに出力をするスクリプトを追加します。
スクリプトはこちらです。
```javascript
var Script3 = pc.createScript('script3');

Script3.prototype.postInitialize = function () {
    console.log(`${this.entity.name} - 3`);
};
```

実行結果はこちらです。すべてのinitializeが呼び出された後にヒエラルキーの上からpostInitializeが呼び出されます。
![スクリーンショット 2022-07-05 14.36.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/b737610a-7ef9-79f4-d569-dc4d8bcbca70.png)
【R】ベクトル中のある長さまでの連続した数値を他の数値に置き換える

計測結果を処理する為に、次のようなベクトルの中の、0が1～4回連続する部分を1に置き換える必要が出てきました。
c(1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0)
↓
c(1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0)

この方法、簡単そうに見えるのですが、なかなかできずに四苦八苦しました。
結局、下記の書き込みを参照してようやく解決出来ました。
https://tagsqa.com/detail/29800

rleという関数を使うのですが、最初に書いたベクトルを代入してみます。
```R
rle(c(1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0))
Run Length Encoding
  lengths: int [1:8] 2 6 6 4 6 2 1 6
  values : num [1:8] 1 0 1 0 1 0 1 0
```
少しとっつきにくいのですが、このように、長さと値が返ってきます。
さらに
inverse.rle
という逆変換をしてくれる機能が素晴らしく使えます。
例えば下記のようになります。
```R
value <- c(1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0)
r <- rle(value)
 
# 代入します
r$values[1] <- 9
 
# 値を見てみます
r$lengths
[1] 2 6 6 4 6 2 1 6
r$values
[1] 9 0 1 0 1 0 1 0

inverse.rle(r)
 [1] 9 9 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 0 0 0 0
```

このように、最初のデータフレームの2連続の1を9に置き換えた答えが返ってきます。

そこで冒頭の問題を解決する関数を作ってみました。
```R
paste_0to1 <- function (data) {
  r <- rle(data)
  rev <- abs(r$values - 1)
  len <- rev * r$lengths
  flag <- which((len < 5) & (len != 0))
  r$values[flag] <- 1
  return(inverse.rle(r))
}
```
皆様の参考になれば幸いです。
pythonを用いて多次元の配列を同時にソートする

# pythonを用いて多次元の配列を同時にソートする


## 目的
複数の配列をある軸を基準にして同時ソートする.\
pythonの組み込み関数zip()の説明

## やりたいこと

```python
rects = [
        [10,20,100,200], 
        [11,21,110,210], 
        [12,22,120,220], 
        [13,23,130,230]
        ]
classes = ["woman", "man", "woman", "man"]
scores = [0.5, 0.2, 0.9, 0.3]
```
上記のような多次元配列reactsとclassesを確信度スコアscoreを基準にして並び替える

### まずは下準備: zip()とは
Pythonの組み込み関数zip()は複数のイテラブルオブジェクト（リストやタプルなど）の要素をまとめる関数。forループで複数のリストの要素を取得する際などに使う。\
forループの中で複数のイテラブルオブジェクト（リストやタプルなど）の要素を同時に取得して使いたい場合は、zip()関数の引数にそれらを指定する。
```python
names = ['Alice', 'Bob', 'Charlie']
ages = [24, 50, 18]

for name, age in zip(names, ages):
    print(name, age)
```
結果
```python
Alice 24
Bob 50
Charlie 18
```
補足:\
zipでひとまとめにする要素の数が異なるときはzip_longest()を用いる. fillvalueを使うとNoneではなく指定したではなく指定した値を入れることができる.
```python
# zip_longest
names = ['Alice', 'Bob', 'Charlie', 'Dave']
ages = [24, 50, 18]

for name, age in zip_longest(names, ages, fillvalue=20):
    print(name, age)
```
結果
```python
Alice 24
Bob 50
Charlie 18
Dave 20
```

## pythonリストの複数同時ソート
```python
#基準にしたいものを一番左に持ってきてzip化する
zip_list = zip(scores, classes, rects)
#昇順にソートする(小 -> 大)
zip_sort = sorted(zip_list)
#降順にソート(大 -> 小)するときはreversa=Trueとする
zip_sort = sorted(zip_lists, reverse=True)
#zipを解凍？する
scores_new, classes_new, rects_new = zip(*zip_sort)
print("scores :", scores_new)
print("classes:", classes_new)
print("rects  :", rects_new)
```
結果
```python
scores : (0.2, 0.3, 0.5, 0.9)
classes: ('man', 'man', 'woman', 'woman')
rects  : ([11, 21, 110, 210], [13, 23, 130, 230], [10, 20, 100, 200], [12, 22, 120, 220])
```

## numpyarray(配列)のソート


```python
 import numpy as np
 #numpy arrayに変換する
 scores_np = np.array(scores)
 classes_np = np.array(classes)
 rects_np = np.array(rects)

#argsort()を用いることで昇順のインデックスを得る
sorted_idx = np.argsort(scores_np)
print("sorted_idx", soeted_idx)
#降順のインデックを得るときは引数に-を加える
 sorted_idx = np.argsort(-scores_np)

#各配列をインデックスをもとにして並び替える
scores_np = scores_np[sorted_idx]
rects_np = rects_np[sorted_idx]
classes_np = classes_np[sorted_idx]
print("scores_np  :", scores_np)
print("rects_np   :", rects_np)
print("classes_np :", classes_np)
```
結果
```python
sorted_idx [2 0 3 1]
scores_np [0.9 0.5 0.3 0.2]
classes_np ['woman' 'woman' 'man' 'man']
rects_np [[ 12  22 120 220]
 [ 10  20 100 200]
 [ 13  23 130 230]
 [ 11  21 110 210]]
```

## 最後に
この記事は[こちら](https://python-ai-learn.com/2021/02/02/sort/)を参考にさせていただきました. ありがとうございました.
[Java] コレクション　List Map Setについて

### はじめに
Java学習中にでてきたコレクションについてまとめました

### コレクションAPI
オブジェクトの集合を管理、操作するJava標準のAPI
オブジェクトの集合　→　コレクション
コレクションの集合　→　要素

よく使うAPI(予め要素の追加・削除などのメソッドが用意されている)
- List
- Map
- Set

### List
配列同様インデックス番号順序に要素を管理するコレクション、要素の重複ok
List自体はインターフェースなのでListを実装している`ArrayList`や`LinkedList`などを使用(import)する必要がある
(`import java.util.ArrayList;`)
##### 配列との違い
配列：要素数の指定が必要
List：要素数の指定が必要なく要素の追加・削除するたびにサイズが増減

##### 基本形
```java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

// ArrayListを生成
List<String> list1 = new ArrayList<String>();

// LinkedList
List<Integer> list2 = new LinkedList<Integer>();
```

##### 操作
```java
/*-- 要素の追加 --*/
list1.add("クッキー");
list1.add("ケーキ");
// 位置の指定追加も可能　クッキー、プリン、ケーキの順になる
list1.add(1, "プリン");
// 位置指定を要素数より多くすると実行時エラー
list1.add(15, "ホットケーキ");

/*-- 要素の取得 --*/
list1.get(0); //=> 「クッキー」が出力

/*-- 要素の存在チェック --*/
list1.contains("プリン") //=> true

/*-- 要素数の取得 --*/
list1.size(); //=> 3を返す

/*-- 要素の削除 --*/
list1.remove("クッキー"); // 文字列として同じなら削除される
list1.remove(0); //=> プリンが削除
// 要素数よりも大きいと実行時エラー
list1.remove(5);
```
##### ArrayListとLinkedListの違い
どちらもimportすればListが使えるようになるが細かい違いがあるらしい
状況に応じ使い分ける必要がある
- インデックス指定で要素を取り出すのはArrayListの方が速い
- 先頭から順に処理をするのはArrayListの方が速い
- 要素の挿入はLinkedListの方が速い
- 要素の削除はLinkedListの方が速い

### Map
「キー」と「値」の組み合わせで要素を管理するコレクション
「キー」：重複はしない、「値」：重複ok
追加した要素の順番は保証されない
`HashMap`や`TreeMap`をimportする

##### 基本形
```java
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

// HashMapを生成する場合
Map<Integer, String> map1 = new HashMap<Integer, String>();

// TreeMapを生成する場合
Map<String, String> map2 = new TreeMap<String, String>();
```

##### 操作
```java
/*-- 要素の追加 --*/
map1.put(0, "クッキー");
map1.put(3, "ケーキ");
// 登録済みのキーで追加すると上書きされる、クッキーが消える
map1..put(0, "プリン");

/*-- 要素の取得 --*/
// 存在しないキーを指定するとnullが返る
map1.get(5); //=> null

/*-- 要素の存在チェック --*/
map1.containsKey(0); //=> true
map1.containsValue("登録してない要素"); //=> false

/*-- 要素の取得はListと同じ --*/
map1.contains("プリン") //=> true

/*-- 要素の削除 --*/
map1.remove(1); //=> 該当がなければ何も起こらない
map1.remove(3, "登録していない要素")　//=> 値が該当しないので何も起こらない
```

### Set
位置（インデックス）やキーなどの要素を特定する概念がない、ただの集合
要素を取り出したい時は繰り返し処理をする（拡張for文やラムダ式）

```java
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

// HashSetを生成する場合
Set<String> set1 = new HashSet<String>();

// LinkedHashSetを生成する場合
Set<Integer> set2 = new LinkedHashSet<Integer>();
```

##### 操作
```java
/*-- 要素の追加 --*/
set1.add("クッキー");
set1.add("ケーキ");
// 位置の指定はできない

/*-- 特定の要素の取得はできない --*/

/*-- 要素の存在チェック、Listと同じ --*/
set1.contains("クッキー") //=> true

/*-- 要素数の取得、同じ --*/
set1.size(); //=> 3を返す

/*-- 要素の削除、インデックス指定はできない --*/
set1.remove("クッキー"); // 文字列として同じなら削除される
list1.remove("登録してない要素"); //=> 何も起こらない
```

### 最後に
Railsでは何も考えずに使ってた配列が、Javaでは配列・コレクションで違いがあるという認識をしました
使いながらもっと理解していこうと思います

閲覧頂きありがとうございました！
ワイ記法でちょっとした要件定義をしてみた話

※関西型言語が実務の中で役に立った話です。
※今回はノンフィクションです。

# 社内用システムを作るチーム[^1]に異動したワイ

ワイ「今日は社内用のWebシステムの改修をして行くでぇ〜」
ワイ「ほな、[後輩くん](https://qiita.com/fuwasegu)が作った**タスク一覧リスト**から」
ワイ「タスクを見つけていこか」
ワイ「どれどれ・・・」

> #### タスク一覧
> - 社員一覧ページで毎回リロードが走るのが面倒臭い

ワイ「社員一覧ページで・・・」
ワイ「毎回リロードが走るのが面倒臭い・・・」
ワイ「うーん、よう分からんな」
ワイ「よう分からんけど、なんとなく適当に『社員一覧ページ』を修正してみよかな」
ワイ「いや、でも・・・修正内容が間違ってて、手戻りが発生したら嫌やしなぁ」
ワイ「せや！」
ワイ「ワイの得意な`ワイ記法`で、タスク内容のすり合わせをしてみよか！」

# ワイの送った内容

> ワイ「後輩くん」
> ワイ「このタスク、こんな認識で合っとるかい？」

#### ワイの書いたユーザーストーリー
> ユーザー「なんか、猛烈に社員の一覧を見たいで！」
> ユーザー「せやから『社員一覧』ページに移動や！ポチッ！」
> 
> ページ『社員リストを読み込み中・・・』
> ページ『ほい、社員の一覧を表示したで！』
> 
> ユーザー「読み込みにけっこう時間がかかったな」
> ユーザー「よーし、ほな次は別のページを見てみるで！」
> 
> 〜10秒ほど他のページを閲覧〜
> 
> ユーザー「次はまた『社員一覧』ページに戻るで！ポチッ！」
> 
> ページ『社員リストを読み込み中・・・』
> ページ『ほい、社員の一覧を表示したで！』
> 
> ユーザー「あれ、また読み込みに時間がかかっとる」
> ユーザー「ちょっと別のページを見てから『社員一覧』に戻っただけなのに」
> ユーザー「こんなに待たされるんかいな・・・」
> ユーザー「これ、キャッシュしておいて、サクッと表示してくれんかな・・・」
> ユーザー「社員一覧の中身なんて、1日に何回も変わるものでもないんやから・・・」

# 満足ワイ
ワイ「よーし、これで・・・」

> ワイ「ワイはこういう理解をして実装に臨もうとしてまっせ〜」

ワイ「っていうことが可視化できたから」
ワイ「もしなんか誤解が生じてるなら、ツッコんでもらえるはずやろ」
ワイ「**ワイ記法**が得意な**ワイならでは**のやり方や！」

# 後輩くんからの返信
> 後輩くん「だいたい認識あってますね〜」
> 後輩くん「僕もちょっと具体例を書きますね〜」

#### 後輩くんの書いたユーザーストーリー
> 【具体例】
> ユーザー「社員一覧ページを見てみよか」
> 
> （一覧ロード中．．．）
> 
> ユーザー「まずは A さんや（ポチ）」
> ユーザー「ふむふむ、A さんはTOEICで700点も取ってるんやな、すごいなぁ」
> ユーザー「じゃぁブラウザバックして、Bさんを探そか」
> 
> （一覧ロード中．．．）
> 
> ユーザー「（ロード長いな．．．）」
> ユーザー「じゃぁBさん（ポチ）」
> ユーザー「BさんはQiitaやnoteなど、アウトプットを頻繁にしとるんやな」
> ユーザー「じゃぁ次にCさんに行こうか」
> 
> （ブラウザバック）
> （一覧ロード中．．．）
> 
> ユーザー「また読み込んどるんか！」
> ユーザー「何回待たすねん！」

# 理解ワイ
ワイ「ふむふむ、なるほどな」
ワイ「よーく分かったで」
ワイ「つまり、問題は・・・」

- 「社員一覧ページ」と「社員詳細ページ」は、行き来しながら閲覧することが多い
- その度に長時間のローディングが起こると、ユーザー体験が悪い

ワイ「↑こういうことやな！」
ワイ「せやから、解決策は・・・」

- APIからの取得データをキャッシュして、高速に表示されるようにする

ワイ「↑これやな！」

# 理解した上でストーリーを修正
ワイ「よっしゃ、ワイの書いたストーリーも修正してみよ！」
ワイ「カタカタカタカタ・・・ッターーン！」
ワイ「できたで！」
ワイ「後輩くんに確認や！」

#### ワイの書いたユーザーストーリー（修正版）
> 〜（省略）〜
> ページ『社員リストを読み込み中・・・』
> ページ『ほい、社員の一覧を表示したで！』
>
> ユーザー「読み込みにけっこう時間がかかったな」
> ユーザー「よーし、ほな『片岡　俊行』（社長）の詳細ページを見てみるで！ポチッ！」
> ユーザー「なるほどな、なんの資格も持ってないんやな」
> ユーザー「次は、また『社員一覧』ページに戻るで！」
> ユーザー「ブラウザバックや！ポチッ！」
> 
> ページ『社員リストを読み込み中・・・』
> ページ『ほい、社員の一覧を表示したで！』
> 
> ユーザー「あれ、また読み込みに時間がかかっとる」
> ユーザー「詳細ページを見てから『社員一覧』に戻っただけなのに」
> ユーザー「こんなに待たされるんかいな・・・」
> 〜（省略）〜



ワイ「送信、と」
ワイ「おっ、後輩くんからお返事や」

> 後輩くん「タスクの認識あってます！」

# 分かりやすかった
ワイ「ユーザーさんの体験が**どんな風に損なわれているのか**・・・」
ワイ「そういうのを表現するのに`ワイ記法`を使うの、悪くないかもな」
ワイ「っていうか後輩くん、ワイ記法メチャクチャうまいな！」
ワイ「できるんなら初めからこれくらい書いておいて欲しいわ！」

# まとめ
- ワイ記法、ユーザー体験を可視化するのに向いてそう
- 「こちらは、こんな理解をしましたよ〜」ということが可視化される
    - それが合っているにしろ間違っているにしろ、可視化されることで議論が一歩前に進む

ワイ「↑こんな感じやな」
ワイ「これ、Gitで管理したら、修正した時の差分も見れて」
ワイ「履歴も残せて、いい感じかもな」
ワイ「今度またやってみよ！」

**〜おしまい〜**

# おまけ
https://twitter.com/Yametaro1983/status/1544582941506170880?s=20&t=egx_Kpc47qJezi0ykCV_Jg

[^1]:「コーポレートエンジニアリングチーム」という名前のチームです。
クロスサイトスクリプティング（XSS）のテスト

# XSSのテスト

構成
Java Spring Boot
Tymeleaf

```コントローラ.java
	/**
	 * 
	 * @param model
	 * @param name
	 * @param response
	 * @return
	 */
	@GetMapping("/xss")
	public String xss(Model model, @RequestParam(name = "name", required = false, defaultValue = "") String name, HttpServletResponse response) {
		model.addAttribute("name", name);
		Cookie cookie = new Cookie("id", "testCookie"); // Cookieの作成
	    cookie.setMaxAge(265 * 24 * 60 * 60); // Cookieの残存期間（秒数）
	    cookie.setPath("/"); // Cookieの適用対象となるサーバ上のパス
	    response.addCookie(cookie);
		return "xss";
	}
```

```xss.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>登録</h2>
	<form action="xss">
		<div>名前：</div>
		<input type="text" name="name" value="">
		<div>
			<button type="submit">OK</button>
		</div>
	</form>

	<h2>登録前の確認</h2>
	<form action="xss">
		名前：
		<th:block th:if="${name}">
			[(${name})]
		</th:block>
		<div>
			<button type="submit">OK</button>
		</div>
	</form>	
</body>
</html>
```

:::note info
[(〜〜〜)]はアンエスケープインライン。コードをエスケープしない。
Tymeleafのthタグやインラインはデフォルトでエスケープするので、通常のHTMLと同じくエスケープ察せないように今回はアンエスケープインラインをあえて使用する。
:::

攻撃者を装って、以下のコードを打ち込んでみる
```
<script>console.log(document.cookie)</script>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/d64ec7db-ed19-cf04-64a4-4ae99c895ee8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/d9f92720-5d60-8032-dbe1-254b31f5724d.png)

スクリプトが上手く動いた。

続いて、実際にリダイレクト先を指定する。
```
<script>window.location='http://localhost:8080/xss?'+document.cookie;</script>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/705b2297-f7e2-9330-7f56-3e19b7ef44bc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/ec865446-1215-3cc4-6b52-716b230fd71c.png)


URLを見てわかるように元画面のIDが送信されている。

## 対策
例えばtymeleafの場合、デフォルトエスケープ処理になっている為
アンエスケープインライン`[()]`を使用せず、エスケープする通常のインライン`[[]]`を使う。

```diff_html
- [(${name})]
+ [[${name}]]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/ca0cffb1-2ba5-2a31-bce6-a34e6594b00c.png)
エスケープされた為、スクリプトタグと認識されず画面上にテキストとして表示された。

htmlでDBの値を使用してページ生成するような場合は、
htmlで特殊文字のエスケープ処理をする。
今回みたいにhtml生成時に画面側でサニタイジングしたりや、サーバ側でバリデーションチェックしたりする。
特殊文字のみを置換するように対策していても文字コードを突いた攻撃もあるので注意。
HTTPレスポンスに設定されるcharsetも正しく設定しておく。
aws ec2 の使い方 (aws-cli)

インスタンスがひとつの場合の InstanceId の調べ方

```bash:go_list.sh
aws ec2 describe-instances > tmp01.json
jq .Reservations[0].Instances[0].InstanceId tmp01.json
```

インスタンスのスタート

```bash:go_start.sh
aws ec2 start-instances --instance-ids i-0f619596fcebda123
```

インスタンスのストップ

```bash:go_stop.sh
aws ec2 stop-instances --instance-ids i-0f619596fcebda123
```

## 実行中のインスタンスのパブリックIPアドレスを調べる方法 ##

```bash:get_state.sh
jq .Reservations[0].Instances[0].InstanceId $1
jq .Reservations[0].Instances[0].State $1
jq .Reservations[0].Instances[0].PublicIpAddress $1
```

実行方法

```bash
./get_state.sh instance.json
```

実行結果

```
$ ./get_state.sh instance.json 
"i-0f619596fcebda123"
{
  "Code": 16,
  "Name": "running"
}
"13.230.15.58"
```

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

```text
$ aws --version
aws-cli/2.7.27 Python/3.9.11 Linux/5.19.4-arch1-1 exe/x86_64.arch prompt/off
```
javaScriptで固定されたD-Dayを作り方




- 固定された入力値
　⇒クリスマスのD-Day

---
必要なページ
---

1．index.html
　　⇒画面に表示されるページ
2.　index.js
　　⇒機能のページ

------
固定された入力値
--
INDEX.HTML
```
<!DOCTYPE html>
<html>
  <head>
    <title>Time Until Christmas Eve</title>
    <meta charset="UTF-8" />
  </head>
  <body>
    <h1>Time Until Christmas Eve</h1>
    <h2 class="js-clock"></h2>
    <script src="index.js"></script>
  </body>
</html>
```
INDEX.JS
```
const clockTitle = document.querySelector(".js-clock");

function clock(){
  const dday = new Date("Dec 25, 2022, 00:00:00").getTime();
  let today = new Date();
  let dClock = dday - today;
  let chrD = Math.floor(dClock / (1000*60*60*24));
  let chrH = Math.floor(dClock / (1000*60*60)%24);
  let chrM = Math.floor(dClock / (1000*60)%60);
  let chrS = Math.floor(dClock / 1000%60);
  
  chrD = String(chrD).padStart(2, "0");
  chrH = String(chrH).padStart(2, "0");
  chrM = String(chrM).padStart(2, "0");
  chrS = String(chrS).padStart(2, "0");

  clockTitle.innerText = `${chrD}d ${chrH}h ${chrM}m ${chrS}s`;

 if(dday < today){
   return clockTitle.innerText = "Merry christmas!";
  }
}

clock();
setInterval(clock, 1000);
```
1. document.querySelector : class="js-clock"の一番目の要素を持つ
2. clock() : 他のイベントがないからすぐ作動
   getTime() : Date(値)をmillisecond(1/1000秒)で返還
　 ⇒Math.floor : Math.floor(値)の最大の定数を変換
3. padStart() :　望む様　01、02　／　出る様　1、2
　　⇒　表示 : 2 、なければ 0
4. innerText : TEXTで入力
5. setInterval(clock, 1000)　:　1秒ごとに実行
---
完成場面
--
* CSS変更は自身の好み
<img width="80%" src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633581/908482fb-5792-f426-a3b3-1b863405bd49.png" />
プログラミング1年生のPythonメモ②～例外と例外処理～

## はじめに
:hatching_chick::hatching_chick::hatching_chick:
こんにちは。
文系出身のシステムエンジニア1年生です。
（いつの間にか入社2年目になってしまいましたが、気持ちが1年目なので1年生です。）



さて、前回の記事では「エラーには2種類ある」という話をしていました。
[プログラミング１年生のPythonメモ①～エラーの種類～](https://qiita.com/sa_6ebdc2/items/c543742960c7f9a2ba22)
>間違ったプログラムを動かそうすると発生するエラー。
これらは大きく2つの種類に分けることが出来ます。
一つはそもそも動かない（動かすことが出来ない）もの。
もう一つは動くけれど途中で止まってしまうものです。
一般的に前者はエラー（構文エラー）、後者は例外と呼ばれます。

今回は後者である<b>「例外」</b>について取り上げてみようと思います。



## 例外とは

構文ミスなどによって、そもそも実行が出来ない<b>構文エラー(Syntax Error)</b>に対し、
動かすことは出来るが、途中で止まってしまうエラーのことを<b>例外(exception)</b>と呼びます。


処理が途中で止まってしまう原因としては、
- ユーザの入力値が間違っている
- 関数に指定された引数が渡されていない
- ネットワーク等の環境によって処理が実行できない

…などが想定されます。


```python:例
def add_5 (num):
    add_num = num + 5
    return add_num
```

例えば、もしこのような関数の引数(ここではnumのこと)に
数値の“10”ではなく、文字列(漢数字)の“十”を渡してしまうと
`文字列 + 数値`　は当然実行できないためエラーとなります。

構文自体は合っているのに、引数が想定と違う形で入力されてしまうと、
この関数の処理はここで停止してしまうのです。

こういったタイプのエラーを<b>例外</b>といいます。


そして、このような予期せぬエラー(例外)に出会ったとき、
そこでプログラムがが止まったままになってしまわないよう、
あらかじめコードを書いておいて対処してしまおう！というのが、次に紹介する<b>例外処理</b>です。


## 例外処理


<b>例外処理</b>とは、実行しているプログラムが何らかの理由でエラーとなった場合、
そこでの処理を一度中断して、別の箇所に記載された処理を行うことです。

これには様々な書き方があるようですが、
今回はひとまず、主な方法を2つだけ紹介したいと思います。（1年生ですし:hatching_chick:）


### try-except講文

例外処理の基本的な書き方の1つが<b>try-except講文</b>です。

```python:try-except構文
def add_5 (num):
    try:
        add_num = num + 5　　　　#ここでエラーが起きれば…
        print(f"add_num is {add_num}")
        return add_num
    except:　　　　　　　　　　　 #exceptブロックの処理へ移動！
        print("Error!!!")　　　  #"Error!!!"と表示させる
```
例えば上記のプログラムなら、最初は順番通り`tryブロック`の処理を行いますが、
エラーが発生した場合はすぐに`exceptブロック`の処理へ移動します。
こうすることで、プログラムが途中で動かなくなってしまって終わり…という事態を回避できます。


### if文

if文を使うことで、エラーを事前に回避するという方法もあります。
```python:if文
def add_5 (num):
    if not instance(num, int):　　　#"もし整数じゃなかったら…"
        print ("入力値が無効です…")　#コレを表示！
        return False
    add_num = num + 5　　　　　　　　#本来やりたい処理↓↓↓
    print(f"add_num is {add_num}")
    return add_num
```
ここではisinstance関数※1を使って、numに入る値が整数かどうかを判断しています。
もし整数以外の値が入れば、“入力値が無効です…”と表示され、
整数であれば、本来の足し算処理が行われます。

このようにif文を使って、事前に入力値をチェックしてエラーを回避するという書き方もあります。

※1　isinstance関数…第1引数に取った変数が、第2引数のオブジェクトかを判定する関数。ここではnumが整数であるかどうかを判断している。


## さいごに
今回は「例外」という種類のエラーと、それに対する「例外処理」について簡単にまとめてみました。
特に例外処理についてはまだまだ多くの書き方があり、複雑な処理を実行しようとすればするほど、関数や構文の組み合わせが必要になってくるようです。

とはいえひとまず、「例外？例外処理？とはなんぞや…」をざっくり知るにはこのくらいで…
ありがとうございました！

:hatching_chick::hatching_chick::hatching_chick:
PsychoPy Soundのduration制御について


## はじめに
PsychoPyで実験タスクのバックグラウンドでメトロノームを鳴らす実装でハマったので，Soundコンポーネントの挙動から洗い出して整理しました．
基本的に実装はBuilderで完結させます．
ちなみにM1MacではPsychoPy自体の挙動がおかしい時がある気がしますね．．．

## 環境
- macOS Monterey v12.3.1 (M1チップ)
- PsychoPy standalnoe v2021.2.3

## 概要
ハマりポイントとしては，Builderが生成するコード（``hogehoge_lastrun.py``）にdurationに関与するパラメータが複数あるというか，Soundコンポーネントの仕様が以下のようであるという点です．

制御の概要図としてはこんな感じ．
ざっくりいうと，SoundコンポーネントのConstructer引数のsecsとstop()メソッドを呼ぶタイミングの整合性が取れていないと，（おそらく）無音状態が再生され続けるというものです．
手っ取り早く解決するには，secsを十分大きく取ってやれば良いはず．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203543/41539e1f-3974-900e-aac8-7e9a26c5dbb1.png)

## Builderで生成されるコード

### Builder生成コードの挙動確認
以下のような構成で検証します．Soundコンポーネント（mtr）以外は無視してもらって構いません．
![スクリーンショット 2022-07-01 12.34.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203543/41111851-4335-4a03-cd06-5842a8c0cc03.png)

このpsyexpファイルからコードを生成．
mtrのduration制御に関係がある箇所は，以下3つ．
＃エディタからそのままコピペしたのでインデント崩れはご了承ください．

```python:hogehoge_lastrun.py
# 1つ目
mtr = sound.Sound('A', secs=.2, stereo=True, hamming=True,
    name='mtr')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2つ目
    # update component parameters for each repeat
    mtr.setSound('A', secs=.1, hamming=True)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3つ目
        if mtr.status == STARTED:
            # is it time to stop? (based on global clock, using actual start)
            if tThisFlipGlobal > mtr.tStartRefresh + .1-frameTolerance:
                # keep track of stop time/frame for later
                mtr.tStop = t  # not accounting for scr refresh
                mtr.frameNStop = frameN  # exact frame index
                win.timeOnFlip(mtr, 'tStopRefresh')  # time at next scr refresh
                mtr.stop()
```

- 1,2つ目のsecs
    - 音が鳴り続ける時間を定義するパラメータ
    - 後述する``mtr.status==STARTED``のままということから推察するに，secsは実際に音が鳴る時間を指し，その後はstop()が呼ばれるまで無音が再生されるという事のよう
- 3つ目のIf文内の`stop()`
    - 時間判定し，stopするという処理
    - `stop()`が実行されると，``mtr.status==FINISHED``つまり終了（停止）状態となる

つまり，secsより後にstop()を呼ぶように実装してしまうと，実装者はstopのタイミングで音が止まることを期待するが，実際のプログラムはsecsの時間経過後に音が止まる（無音状態になり）ので，意図した時間よりも早く音が止まってしまうということになりかねる．
**→secとstop判定する時間の大小関係に注意！！**

＃特に，メトロノームのような音の繰り返し処理をしたいときに，codeコンポーネントをごにょごにょするとハマる！

### statusについて
- ``NOT_STARTED``:`play()`以前の状態
- ``STARTED``:`play()`実行後の状態
- ``FINISHED``:`stop()`実行後の状態
という具合に確認できたので，secs経過後＝無音状態が再生されているのではと推測した．

同じSoundコンポーネントで繰り返し再生する場合は，`FINISHED`後に`status = NOT_STARTED`と戻してやれば，再度play()を呼ぶと再生される．
気づいたらOSSコントリビューターになっていた

# はじめに
気づいたらOSSコントリビューターなるものになっていた。本当に些細なPRがマージされただけであるが。

https://github.com/kentcdodds/match-sorter/pull/140

私の想像するコントリビューターとは、言わば天上人と言うべき存在であった。コンピューターの全てを理解した一部の天才エンジニアがその技術力、知見を余すことなく発揮した作品がOSSであると。そう思っていた。

エンジニア歴1年の新人の私から見ればそのような方たちのコードにケチを付けるような行為など恐れ多いにも程がある。ハンターハンターで言えばネフェルピトー、ワンピースで言えばカイドウに対する圧倒的力の差を感じてしまうものである。

しかし、どうやらOSSにPRを投げる行為はそのようなものでないらしい。

様々な方がOSSへの貢献を推奨している。だがそのような記事を見ても、いやいや自分はまだまだだし、、と億劫になってしまう方も多いでしょう。私もその1人だったので。

私と同じく億劫なエンジニア方に向けてOSSへの貢献を少しでも気楽に行えるためのアドバイスを送る。

# 対象読者
- OSS貢献に興味があるがしたことがないエンジニア

# OSSへの貢献を目的としない
まず最初にこの考え方を意識しておくことが大事だと思う。いきなり概念を覆すような話だが重要である。なぜなら、OSSへの貢献ではなく、OSSをより使いやすくするための1つの方法として貢献があるからである。

私自身、OSSコントリビュートするつもりでいたわけではなかった。たまたまちょっとした間違いを見つけてそれを正しただけである。

間違いを見つけたきっかけはライブラリの挙動を理解したいと思ったから。OSSへの純粋な好奇心を持ったおかげでライブラリを手元で起動した際にコントリビュートの発端となるドキュメントのミスに気づけたのである。

私もかつて何度もライブラリのissueを眺めていたがそれだけだとなかなか貢献まで進むことができなかった。しかし、貢献を意識せずに純粋にライブラリを動かしてみようと思ったことがきっかけでOSSへの貢献に寄与したのである。しかもかなりあっさりと。

OSSの貢献はその行為自体を意識しているとなかなか進まないということを自身の経験から学んだ。純粋なライブラリへの興味、より良くしたいという動機が貢献という結果をもたらすのである。

# とりあえずフォークしてみる
先程と連なる話だが、気になったライブラリは手元にクローン or フォークして動かしてみると良い。業務や個人開発の中で実際に使ったことがあるライブラリだと理解も早いはずである。

README にある程度起動方法や、貢献方法などが揃っているライブラリの方が環境構築等で迷うことも無いので積極的に起動してみることをおすすめする。

私自身ライブラリ自体をフォークする経験も初めてだったので最初は多少戸惑った。普段からフォークに慣れているといざPR送りたいと思ったときでも恐れずに行動できるはずである。

# 英語を恐れない
海外製のライブラリが大半なため、PRを送る際に英語は避けることはできないだろう。ただ、英語のやり取りに関しては本当に最小限であり、現代社会では便利なツール( [Deepl](https://www.deepl.com/ja/translator) 等)が様々存在するのでそれらを活用すればなんら問題はないはずである。

https://qiita.com/shikichee/items/a5f922a3ef3aa58a1839

また、上記の記事を見れば分かるように実際に多用される英単語は実にシンプルなものである。奥せずにツールを利用して記載すれば問題なく伝えたいメッセージは必ず通じる。

# おわりに
これからOSSコントリビュートを目指すエンジニア向けに重要な考え方をまとめてみた。この記事をみて少しでもOSSへ貢献のきっかけになれば幸いである。

筆者自身このような記事を書いているのに貢献したことあるのはドキュメントだけってのも少しダサい気がするのでこの記事の考え方を胸に様々なライブラリを動かしてみたいと思う。
IBM 製品利用を助ける動画集！

# はじめに

皆様こんにちは。Kazuyaです。

最近では、製品の開発スピードも速く、なかなかわかりやすい製品の紹介や初級者向け導入のための説明動画を作るのが困難なほどになりましたね。

特に、グローバルチームが英語で作成した動画や文献は見当たるけど、
日本語版があまりない・・・というのに対して、
「**日本のIBM Customer Success チーム**」 が、
そういったお悩みの多いお客様向けの動画を作ってくれています。

これらの動画は、まだ使ったことがない方向けの動画から、中上級者向けの使い慣れた方々向けのものまで取り揃えていて、不定期で新しいコンテンツもアップされているそうなので、何か気になる場合はぜひのぞいてみてください！

# コンテンツ一覧 (2022-06 ～ 2022-07にPUBLISHされた動画)
* [IBM Customer Success Japan](https://video.ibm.com/channel/7Jsjerm2TAQ) ・・・紹介動画
* [自動車のリコール・不具合情報を分析してみた](https://video.ibm.com/recorded/131903514)
* [CP4IのAPI Connectに既存APIを登録して公開する](https://video.ibm.com/recorded/131903442)
* [複数データソースのデータを仮想化してまとめて分析してみよう（AWS、IBM Cloud）](https://video.ibm.com/recorded/131899415)
* [次世代カスタマーサポートソリューション -顧客対応から分析まで-](https://video.ibm.com/recorded/131896001)
* [検索＆分析事例千本ノック1](https://video.ibm.com/recorded/131895892)
* [検索＆分析事例千本ノック2](https://video.ibm.com/recorded/131895893)
* [検索＆分析事例千本ノック3](https://video.ibm.com/recorded/131895894)
* [検索＆分析事例千本ノック4](https://video.ibm.com/recorded/131895895)
* [CP4Dでデータ結合をするツールは？](https://video.ibm.com/recorded/131868194)
* [CP4Dを使って画像分類モデルを作成してみよう-Part 1](https://video.ibm.com/recorded/131842640)
* [CP4Dを使って画像分類モデルを作成してみよう-Part 2](https://video.ibm.com/recorded/131842639)
* [CP4Dを使って画像分類モデルを作成してみよう-Part 3](https://video.ibm.com/recorded/131842633)
* [CP4Dを使って画像分類モデルを作成してみよう-Part 4](https://video.ibm.com/recorded/131842631)
* [Watson Queryでデータ仮想化してみよう part 1](https://video.ibm.com/recorded/131822067)
* [Watson Queryでデータ仮想化してみよう part 2](https://video.ibm.com/recorded/131821879)
* [Watson Queryでデータ仮想化してみよう part 3](https://video.ibm.com/recorded/131821878)
* [Cloud Pak for Dataで、 データ仮想化を始める ~1.準備~](https://video.ibm.com/recorded/131801274)




---

# 免責事項
本記事は、１個人が作成したものであり、所属する企業を代表する公式文書ではありません。
ご紹介する情報の妥当性や、公式な手順との整合性を保証するものでもありません。
説明する製品の販売元の推奨と異なる場合がありますので、異なる場合はサービス・製品を提供する企業の公式見解に倣うまたは、
当該企業の担当者へ直接問い合わせを行うようお願いいたします。
本記事を用いた活動において発生したいかなる損害も、当方では責任を取りかねます。
予めご了承ください。


---
[C#]配下のコントロールを全て取得する[WindowsForms]




検証環境
Windows11
.NET Framework 4.8

配下の子孫コントロールも含めて、持っている全てのコントロールを取得するプロパティはないようです。(あれ～なかったっけ)

ControlクラスはControlsプロパティを持っています。これで子のコントロールを全て取得できます。
が、それより下の孫以降のコントロールは取得できません。
仕方ないので、再帰的に取得してくる必要があります。


```csharp
// 配下のコントロールを全て取得する
private List<Control> GetAllControls(Control parentControl)
{
    var list = new List<Control>();
    foreach (Control ctrl in parentControl.Controls)
    {
        list.Add(ctrl);

        // 配下のコントロールを追加
        list.AddRange(GetAllControls(ctrl));
    }

    return list;
}
```
↑AddRangeメソッドでは追加するリストが0件の場合でも、エラーになったり空白のリストが追加されることはありません。

以下は呼び出し例です。

```csharp
// 呼び出し例
List<Control> editctrl = GetEditControls(this);
```


Linqとかでもっとかっこいい書き方ができそうですが、これでも取れます。。
STM32L010を使い、ざっくり1000で割る(あまり正確では、ない)(1000の割り算)


x Mbed2
x 軽量高速化

目的
大きくなりすぎた桁をざっくり減らす

![o_con561.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/29b26ffa-afff-0b6a-2e2b-233a5b7ed950.jpeg)



計算式


```



1000/15=66
66*1.5=100

100,000/1024=97.65625
97.65625*1.024=100

97.65625*1.0  =97.65625
97.65625*0.024=2.234375

97.65625+2.234375=100

100,000*1.024=102.400
102.400/1024=100


前提
1 1000 01 10 1010 0000‬. (100,000)
1 1000 01.10 1010 0000‬  (97.65625)　右10ビットシフト



1 1000 0110 1010 0000‬ (100,000)  97.65625

       1001 0110 0000 (  2,400)   2.34375
-----------------------------------------
1 1001 0000 0000 0000 (102,400) 100.0


1 1000 0110 1010 0000‬ (100,000)  97.65625

       1001 1000 1001‬ (  2,441)   2
-----------------------------------------
1 1001 0000 0010 1001‬ (102,441) ‬100


         00 0001 1001 (     25)   0.024
         00 0001 1000 (     24)   0.024


97.65625 * 0.24 = 23.4375

2,457,600 / 1024 = 2400

100,000 * 24.576 = 2,457,600
                   2,457,600/1024=2400


100,000 * 25     = 2,500,000
                   2,500,000/1024=2,441‬


((n + ((n * 25)>>10))>>10)



```

プログラム


```c++


//B_DIV1000_010_1

#include "mbed.h"

RawSerial pc(PA_2, PA_3); //010

//1000の割り算 だいたい正しい。
#define DIV1000(n) ((n+((n*25)>>10))>>10)

//10の割り算 0から9999までは、正しい。
#define DIV10(n) (((n*409)+((n*154)>>8))>>12)

int main() {

    int d;
    char data[15];

    pc.printf("START\r\n");

    while(1){

        d=123456;

        d=DIV1000(d);        

        data[4] = 0;
        data[3] = '0' + (  d - (DIV10(d) * 10)  );  // '0'+(d%10)
        d = DIV10(d);
        data[2] = '0' + (  d - (DIV10(d) * 10)  );  // '0'+(d%10)
        d = DIV10(d);
        data[1] = '0' + (  d - (DIV10(d) * 10)  );  // '0'+(d%10)
        data[0] = '0' +  DIV10(d);                  // '0'+(d/10)

        pc.printf(data);
        pc.printf("\r\n");
        wait_ms(1000);

    }//while

}//main



```




https://paiza.io/ja/projects/new?language=c


テスト



```c++



//1000の割り算 だいたい正しい。
#define DIV1000(n) ((n+((n*25)>>10))>>10)

#include <stdio.h>
int main(void){

    int n01 =  0;

    for(int ii = 0;ii <= 400000;ii=ii+1000){
        
        printf("[%d]=",ii);
        n01=DIV1000(ii);
        //n01=((ii+((ii*25)>>10))>>10);
        printf("[%d]\r\n",n01);
        
    }//for
}



```