OmniAICreator/Qiita-1.07M huggingface dataset:
【AIプラレール】ラズパイ + 機械学習 で自動運転（概要編）

「プラレール」に「ラズパイ」を載せて、自動運転に挑戦します。
※今回の記事では、概要編として概観を記しておきたいと思います。
<div align="center">
<img width="450" alt="AIプラレール" title="AIプラレール外観" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507379/70e9d66a-9ae9-b201-bdc1-5deab5f98913.jpeg">
</div>

# "AIプラレール" とは
世の中に「AIプラレール」という言葉があるのかは定かではないですが、この記事ではAIプラレールと称して、プラレールの動力をラズパイとモータードライバー経由で制御し、速度調整（前後進・停止）を行えるようにします。
加えて、Piカメラの画像から物体識別を行い、その結果により停止・前進等の自動運転できる環境を整えます。
※おまけとして、スマホから手動遠隔操作できるようにもします。（ラジコンみたいな感じ）
<div align="center">
<img width="350" alt="AIプラレール" title="AIプラレールのイメージ図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507379/4ea0c80a-3f8d-c760-0f81-cefc338e99c1.png">
</div>

# 環境
実装環境は以下の通りです。（2020年2月時点）

- AI環境（パソコン）
    - GPU：GeForce GTX 1070（Driver Ver418.87.01, CUDA Ver10.1）
    - ホストOS：CentOS release 7.7.1908
    - コンテナ：Docker Ver19.03.4（イメージ：Ubuntu 18.04.3 LTS）
- エッジ環境（プラレール）
    - シングルボード：Raspberry Pi Zero WH
    - カメラ：Raspberry Pi Camera V2
    - プラレール：S-60 EF66電気機関車（中古）
    - モータードライバー：HiLetgo L9110S
    - バッテリー：Anker PowerCore 5000、cheero Canvas 3200mAh IoT機器対応
    - USBケーブル：そこらへんに転がっているType-A（オス）とmicro-B（オス）の口があるもの
    - ジャンパーワイヤーを少々（取り回しを良くするために、ハウジングキットがあると尚良し）
    - ミニブレッドボード（無くてもよいけど、あった方が試行錯誤するときに便利）
- モバイル環境
    - 手持ちのスマホ（私はZenFone3、古い）

# 仕組み
### プラレール
プラレールの各車両の役割は次の通りとしました。

- **1号車**：一般的なプラレールと同じで動力車両となります。DCモーターはプラレールに搭載されているものを流用します。電池はダミー電池に置き換え、モータードライバーに接続します。また、Piカメラを搭載し、運転席から見える景色を撮影できるようにします。
- **2号車**：プラレールの動力を制御するシステム車両となります。ラズパイにはモータードライバー（動力制御用）とPiカメラ（物体識別用）を接続します。
- **3号車**：DCモーター（モータードライバー経由）とラズパイへ給電を行う電源車となります。バッテリーは、合計2つ搭載します。
<img width="550" alt="AIプラレール" title="物理構成図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507379/af19ff8a-406d-ff3b-3288-e1d3d61c3b7f.png">

### システム
エッジからバックエンドまでの各システムの役割と、システム間の連携は以下の通り。

- **AI環境**：AI環境では、車両から送られてくる画像を常時ひたすら物体識別を行い、特定の物体（人）を検知した場合に、エッジのプラレールに対して「停止」の命令を発します。
- **エッジ環境**：プラレールの電源を起動し、車両の走行や停止を行います。初期走行は、初期設定として走行状態とするか、モバイル環境からの操作で走行を開始します。AI環境から停止を命令を受けた場合には、一定期間停止（今回は適当に5秒間）し、その後は自動で運転を再開します。
- **モバイル環境**：プラレールの電源が起動した状態で、スマホのブラウザに表示されている操作画面から、前進・後進・停止の操作を行います。

<img width="550" alt="AIプラレール" title="処理フローのイメージ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507379/86da3d39-b67a-a69e-0fa1-8ae092e1d24a.png">

# AIプラレール概要編のまとめ
今回は、概要編として以下の内容をまとめておきました。
- AIプラレールのコンセプトとイメージ
- 物理・論理のハイレベルアーキテクチャ
- 工作に必要な（使った）材料の明示

次回は、実装編を公開予定（時期未定）です。
JSでawait出来るsetTimeoutがたった１行で作れるって話

## コード 📃

```js
await new Promise((resolve) => setTimeout(resolve, 3000));
```

以上！
めちゃくちゃ簡単🙌

:::note warn
awaitを使っているので、これを使う関数にはasyncを付ける必要があるので要注意！
:::

## 簡単な解説 📗

:::note info
前提知識として、Promise() をなんとなく理解している必要があります。
:::

1行だと少し理解するのが難しいので分解してみます。

```js
await new Promise((resolve) => {
  setTimeout(() => {
    resolve();
  }, 3000)
});
```

```:処理の流れ
１．Promise内でsetTimeoutを実行する
２．setTimeoutが指定時間(3000ms)だけ待つ
３．時間が経ったらresolve()を実行して終了！
```

`await new Promise()`の組み合わせのおかげで`resolve()`が実行されるまでは処理が止まるって感じですね🙌
逆に`resolve()`が実行されないとエンドレスPromiseになりますｗ


## おまけ 🌸

本家(?)のjava様にならってjavascriptでも**sleep関数**を作ってみました！！

```js
/**
  * 処理を指定時間だけ止める
  * @param { number } time 止める時間(ms)
  */
async function sleep(time) {
  await new Promise((resolve) => setTimeout(resolve, time));
}

// 以下は実行用の記述
async function hoge() {
  // 1秒待ってから終了ログを出す
  console.log('はじめ！');
  await sleep(1000);
  console.log('おわり！');
}
hoge();
```
なぜcreateメソッドのparamsのみparams.requireメソッドが代入されるのか。

理解が曖昧だったため、整理のために記事を投稿。

それは**createメソッド**とそれ以外において、<font color="Red">役割が異なるため</font>である。
また、ここでは、newとindexメソッドは省く。

**createメソッド**の役割は、newのviewにおいて記載され、**ストロングパラメーター**となった(許可された)情報を取得し、保存することにある。
そのため、データベースのテーブルから、レコードを一つ取り出すメソッドであるfind(params[:id])は使えない。
そのため、**createメソッドに対し、params.requireの中身を代入すること**になる。

```ruby:task.controller.rb

  def create
    @task=Task.new(task_params)
    if @task.save
      redirect_to tasks_path, notice: "作成しました"
    else
      render 'new'
    end
  end

private

  def task_params
    params.require(:task).permit(:title, :content, :start_time, :is_done, :pet_id, :family_id)
  end
```
<br><br>

一方、show,destroy,edit,updateにおいては、<font color="Red">テーブル内に保存されている1つのidに紐づいた情報を取得</font>したい。
そのため、上記の場合には、**find(params[:id])メソッド**を使うことになる。

```ruby:task.controller.rb
  def show
    @task = Task.find(params[:id])
  end

  def destroy
    @task = Task.find(params[:id])
    @task.destroy
    redirect_to tasks_path, notice:"削除しました"
  end

  def edit
    @task = Task.find(params[:id])
  end

  def update
    @task = Task.find(params[:id])
    if @task.update(task_params)
      redirect_to tasks_path, notice: "編集しました"
    else
      render 'edit'
    end
  end
```
以上である。
JSONを受け渡しするRails APIのrequest specの書き方

# はじめに
一部React化で久しぶりにAPIを作成しました
JSONを受け渡しするRails APIのrequest specの書き方まとめです :sparkles: 

## headersにContent-Typeを追加する
headersに`'Content-Type' => 'application/json'`を追加する
これでJSONのparamsを渡すことができるようになります

追加しないとデフォルトでは
`"CONTENT_TYPE"=>"multipart/form-data"`となり
数値やbooleanが文字列に変換されてしまいます
```rb
  describe 'PATCH #update' do
    subject { patch xxx_path(article), headers: { "Content-Type" => "application/json" } }
    ...
  end
```

## JSONのparamsを用意する
```rb
let!(:params) { { name: 'タイトル', body: '本文' }.to_json }
```

:::note warn
`to_json` を使ってHashからJSONにパースするのがポイント
パースしないと
`ActionDispatch::Http::Parameters::ParseError`
を吐いて500が帰ってきます :sweat_drops: 
:::

## requestにparamsを渡す
```rb
  describe 'PATCH #update' do
    subject { patch xxx_path, params: params, headers: { "Content-Type" => "application/json" } }
    ...
  end
```

## テストする
`as_json`はハッシュのキーをシンボルから文字列に変換してくれます :raised_hands_tone1: 
最初から文字列のハッシュを書いてもOKですが、キーがシンボルの方がスッキリするので今回はシンボルで定義してから`as_json`しています
```rb
  it 'creates article and returns correct response' do
    expect { subject }.to change(Article, :count).by(1)
    expect(Article.last.name).to eq 'タイトル'
    expect(Article.last.name).to eq '本文'
    expect(response).to have_http_status 200
    expect(JSON.parse(response.body)).to include({
      article: { id: 1, name: 'タイトル', body: '本文' }
    }.as_json)
  end
```

# まとめ
超簡単にですがRails APIのrequest specの書き方をまとめました
あとは `params`や `it`の中身を変えるだけで応用できるかなと思います
間違いなどあればコメントで指摘していただけますと幸いです！

# 参考記事
https://qiita.com/takano-h/items/c752f7a689429f0220da

https://qiita.com/yuki_0920/items/ffbc10c81d48926d9a56

https://shinkufencer.hateblo.jp/entry/2019/04/08/233000
[CSS小ネタ] React でフッターの下の余白がなかなか消えなかった話

## やりたいこと・お悩み
メインのコンテンツのボリュームが少ない時に、footer の下の余白を消したい。少ない時は下にくっついていて、多い時は押し出されてほしい。

解決策は、```flex``` なり ```grid``` なりを使ってやる。
やったんだけど、余白が消えなかった。```html/css``` だけだとうまくいくのに、なんで？！

## ```html/css``` 的な解決策（一般論）

```html
<html>
  <head>...</head>
  <body>
    <header>header</header>
    <main>main</main>
    <footer>footer</footer>
  <body>
</html>
```
なる html に対し、css を書いていく。

### ```flex``` の場合

```css
body {
  display: flex;
  flex-flow: column;
  min-height: 100vh;
}
main {
  flex-grow: 1;
}
```

### ```grid``` の場合

```css
body {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 100%;
  min-height: 100vh;
}
```

flex か grid は、どっちでも良いんじゃないかと。1次元のレイアウトだし、flex で良いかなー。

## うまくいかない理由

<b>body に style を当てているから。親違い。</b>

前述の ```html``` のつもりで書いたものは、react 上では、実際には、以下のようになる。

```html
<html>
  <head>...</head>
  <body>
    <div id="root">
      <header>header</header>
      <main>main</main>
      <footer>footer</footer>
    </div>
  <body>
</html>
``` 

```<div id="root" />``` 犯人はこいつだ！ ```body``` の中に要素が1つしかないので、```flex``` も ```grid``` も効かない。

## 解決方法

```body``` ではなく、```#root``` にスタイルを当てるか、別途 ```div``` で囲んで、それに当てる。
```#root``` にスタイルを当てるのは、何となく抵抗があったので、```div``` でラップしてそれに当てる。

元のレイアウトテンプレート

```typescript:layout.tsx
import { ReactNode, FC } from 'react';
import { Footer } from '../../organisms/layouts/Footer';
import { Header } from '../../organisms/layouts/Header';

type Props = {
  children: ReactNode;
};

export const Layout: FC<Props> = (props) => {
  const { children } = props;
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
    </>
  );
};
```

これを、私は emotion を使っているので、

```typescript:layout.tsx
/** @jsxImportSource @emotion/react */
import { ReactNode, FC } from 'react';
import { css } from '@emotion/react';
import { Footer } from '../../organisms/layouts/Footer';
import { Header } from '../../organisms/layouts/Header';

type Props = {
  children: ReactNode;
};

export const Layout: FC<Props> = (props) => {
  const { children } = props;
  const wrapper = css`
    display: flex;
    flex-flow: columns;
    min-height: 100vh;
    main {
      flex-grow: 1;
    }
  `;
  return (
    <div css={wrapper}>
      <Header />
      <main>{children}</main>
      <Footer />
    </div>
  );
};
```

そして、元々 body に当てていたものは、消す。```body > div#root > div.wrapper``` となんだかなーって気もするし、異なるレイアウトを使う時などに、同じことを書くことになるかも知れないが、```App.tsx``` に書くのも違う気がするので、これで。```<></>``` も嫌いだし。

以上、CSS 小ネタでした。
Laravel:キー名が id 以外の時にbelongsToManyメソッドを使う方法

### 環境
- Laravel 8.x

### 概要
- テーブルが多対多の関係の時にbelongsToManyメソッドを使うが、キー名が id 以外の場合どうするのか調べた

### 結論
- belongsToManyメソッドの第５、第6引数を使用して対応する
    - https://laravel.com/api/8.x/Illuminate/Database/Eloquent/Concerns/HasRelationships.html#method_belongsToMany

### 具体例
以下のテーブルがあるとする

- users

|  user_num  |  name  |
| ---- | ---- |
|  1  |  foo  |
|  2  |  bar  |

- roles

|  role_num  |  name  |
| ---- | ---- |
|  1  |  baz  |
|  2  |  qux  |

- role_user(中間テーブル)

|  id  |  user_number  |  role_number  |
| ---- | ---- | ---- |
|  1  |  1  |  1  |
|  2  |  1  |  2  |

上記の様な多対多の関係をEloquentのリレーションで実現する↓

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * このユーザーに属する役割
     */
    public function roles()
    {
        return $this->belongsToMany(Role::class, 'role_user', 'user_number', 'role_number', 'user_num', 'role_num', );
    }
}
```

##### 引数まとめ
1. 関連するモデルクラスの名前
1. リレーションの中間テーブルのテーブル名
1. 接続元の中間テーブルの外部キー名
1. 接続先の中間テーブルの外部キー名
1. 接続元のキー名
1. 接続先のキー名

[Eloquent:リレーション 8.x Laravel](https://readouble.com/laravel/8.x/ja/eloquent-relationships.html)では第4引数の紹介までだったが、[Laravel API](https://laravel.com/api/8.x/Illuminate/Database/Eloquent/Concerns/HasRelationships.html#method_belongsToMany)を見ると第7引数まで指定できると分かった。
これからはLaravel APIをちゃんと見よう。。。
【試験合格記】DOP-C01 && ANS-C00 && SCS-C01 && MLS-C01

お疲れさまです。
表題の試験を更新したため記録として残したいと思います。

# 受けた試験

- DOP-C01( AWS Certified DevOps Engineer - Professional )
    - 受験日: 2022-05-22
    - 受験者スコア: 910/1000
- ANS-C00( AWS Certified Advanced Networking - Specialty (Retiring July 11, 2022) )
    - 受験日: 2022-07-06
    - 受験者スコア: 848/1000
- SCS-C01( AWS Certified Security - Specialty )
    - 受験日: 2022-08-10
    - 受験者スコア: 890/1000
- MLS-C01( AWS Certified Machine Learning - Specialty )
    - 受験日: 2022-08-17
    - 受験者スコア: 777/1000

# 前回の受験記録

- [【試験合格記】AWS 認定 DevOps エンジニア – プロフェッショナル](https://qiita.com/yastani/items/07ebeb3d5dc8aab1df01)
    - 受験者スコア: 760
- [【試験合格記】AWS 認定 アドバンスドネットワーキング – 専門知識(ANS-C00)](https://qiita.com/yastani/items/695d1ebb1ed51f957ab4)
    - 受験者スコア: 不明(採点結果が送られてこなかった)
- [【試験合格記】AWS 認定 セキュリティ – 専門知識(SCS-C01)](https://qiita.com/yastani/items/f77bc9a06affeeccec75)
    - 受験者スコア: 913
- [【試験合格記】AWS 認定 機械学習 – 専門知識(MLS-C01)](https://qiita.com/yastani/items/b02c5b05150bd130a711)
    - 受験者スコア: 902

# 各試験の所感

- DOP-C01
    - 試験問題は前回から更新された気がする
    - 大枠の内容自体は変わらず、実務に直結するAWSサービスの出題がメインだったため高得点を取れた
    - 前回はElastic BeanstalkとOpsWorksが多かったような覚えがあるが、流石に時代の流れか少なくなった印象
    - 代わりにCloudFormationとCDKの比率が上がっていたかもしれない
    - 世に出回っている模擬試験と、Codeシリーズを実務で触っていれば割と余裕と言える
- ANS-C01
    - この試験は上述しているようにリタイアしているためもう受けることはできない
    - 今は `ANS-C01` として、より現代的な試験問題になっているはず
    - 出題傾向はあまり変わっていなかったはず
    - ただしネットワークカテゴリに該当する多くのAWSサービスが実務で使う機会は少ないと思われるので、試験対策は必須
    - Transit Gatewayを有効活用する、VPC Peeringの利点を理解した上で選択する、NACLとSecurityGrouｐの使い分けや、
      DDoS攻撃などの攻撃をどのように防御するのかといったネットワークに関連するセキュリティ対策への深い理解が必要になる
    - 個人差はあると思うが、個人的には難易度は高いという印象
- SCS-C01
    - この試験も前回から大きな変更は無かった気がする
    - Systems Manager ParameterStoreとSecrets Managerの使い分けを理解する
    - KMSとCloud HSMを使用した暗号化、復号化を正しく理解する
    - この1〜2年でずいぶんとAWSセキュリティに慣れ親しんだので無勉でもなんとかなりそうだった
    - もう一段ほど難しくなるとOIDCトークンの使い方や利点を問われる気がするので覚えておいて損は無さそう
    - IAMポリシーの間違い探しを問われる頻度が結構多かったので、日頃からコピペせず最小権限の原則に従って自分で書くようにするのがオススメ
- MLS-C01
    - いくつか出題傾向が変わっているように感じた
    - 想定していた出題範囲から大きく外れた問題が多く、ぎりぎりの点数で合格
    - 機械学習についてまわる専門用語がくせ者、相関関係をメモしないと確実に試験で落とされる
    - 他の試験にも言えるが、模擬試験よりもAWS公式の[試験対策](https://aws.amazon.com/jp/training/classroom/exam-readiness-aws-certified-machine-learning-specialty/)に取り組んだほうが知識の定着には役立つ
    - AWSサービスの組み合わせよりも機械学習そのものに対する基礎知識を問われる問題が多かった気がする

# 受験者に向けたアドバイス

- いつの間にかAWS公式が主体となって試験対策のコンテンツを数多くリリースしてくれるようになったので、どんどん活用しよう
    - 試験ガイド
    - サンプル問題
    - 無料になった模擬試験
    - 試験対策コンテンツなど
- 学習時間はスコアに直結しやすいので計画的に学習をするのがよい
- 勉強を開始する前に試験の予約をしてしまえば勝手にやる気スイッチが入る…はず
- 触ったことのないサービスは率先してAWSコンソールから触ってみるのが大事、問題と記憶がリンクすれば答えも浮かびやすくなる
because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.


### Websocket が CSP に引っかかったときの対処方法

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/4b4c9c9e-fc48-f3b1-dd7b-a317c4529e8c.png)

```bash
renderer.js:1 Refused to connect to 'ws://127.0.0.1:5001/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
```

```diff
  <head>
    <meta charset="UTF-8">
-    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self';">
+    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; connect-src 'self' ws:;">
    <title>Hello World!</title>
  </head>
```

他にもいろいろ引っかかるようであれば、以下を書いておくと回避可能。

```
<meta http-equiv="Content-Security-Policy" content="default-src * gap:; script-src * 'unsafe-inline' 'unsafe-eval'; connect-src *; img-src * data: blob: android-webview-video-poster:; style-src * 'unsafe-inline';">
```
Rust-bindgenでCヘッダを変換した後のunsafe操作メモ

# すごいぞbindgen
rust-bindgenというツールを使うとC言語の.hファイルからバインディングを自動生成してくれます！すごく便利ですね！

https://rust-lang.github.io/rust-bindgen/introduction.html

今回はbindgenで変換した後のお話です。私がCに疎いので間違えた解釈をしていることもあるかもしれませんが、C向けAPIでよくあるパターンとその対処法を書いていきます。


## NULLポインタを用意する

```rust
let nullpo: *mut std::ffi::c_void = std::ptr::null_mut();
```
ハンドル生成でお世話になる。ポインタは`as`でキャストすることもできるみたいです。

## 目的データのポインタからデータをコピーする
```rust
let mut buf = vec![0; length];
let p_buf = buf.as_mut_ptr();
std::ptr::copy_nonoverlapping(p_src, p_buf, length);
```
Cのmemcpyと一緒。引数の順番は違う。~~セグフォの原因だいたいこいつ~~
コピー元がCの世界出身であれば正しくメモリ開放しましょう。

## 大きな構造体のメモリを初期化せずに確保する

```rust
let mut some_big_struct: MaybeUninit<SomeBigStruct> = MaybeUninit::uninit();
//ポインタを得る。
let p_some_big_struct = some_big_struct.as_mut_ptr();
```
初期化にかかる時間すらもったいない人向けです。
`MaybeUninit`は未初期化の変数にアクセスできないように包んでくれます。

## Cstringを作る
```rust
let cstr = CString::new("string").unwrap();
let p_cstr = cstr.as_ptr();
```
これに限らず、as_ptr系のメソッドを使うときはそれが指す領域が存在していないとセグフォします。
ワンライナー癖のある人はポインタだけ生成しないように注意！

参考：

https://qiita.com/dalance/items/a40bcf547215b69859fb

## ライブラリをリンクする
```rust:build.rs
fn main(){println!(r"cargo:rustc-link-lib=dylib=path/to/library")}
```
ビルドスクリプトを書きます。
パスに`.lib`などの拡張子は必要ない。（多分.dllだったり.soだったりの拡張子を無視して扱えるすごいシステム）

## 共用体を使う
```rust
#[repr(C)]
#[derive(Copy, Clone)]
union MyUnion {
    f1: u32,
    f2: f32,
}
```
そもそも共用体の中身はCopy可能でなけらばならないのでCopyトレイトはつけるだけお得。
存在自体がtransmute系のunsafeなので可能な限り使いたくない。


## おわりに
他にもあったら追加します。
【Ruby】1次元配列を2次元配列に変換する実装方法

## はじめに
多次元配列を1次元配列に変換するには`flatten`メソッドを使用すればよいですが、その逆の1次元配列を多次元配列にするメソッドはないなと思い、実装してみました。
多次元配列と言いながら、今回は2次元配列に変換する方法になります。
## 実装
```ruby:.rb
puts "カンマ区切りで複数の数値を入力してください"
input_array = gets.chomp.split(",")

puts "2次元配列の行と列のどちらを固定しますか？（'行'or'列'を入力してください）"
select = gets.chomp

# 列が選択されたときの行と列の数を算出
if select == "列"
  puts "列数を入力してください"
  new_column = gets.chomp.to_i # 2次元配列の列数
  new_line = ((input_array.count)/new_column.to_f).ceil # 2次元配列の行数
end

# 行が選択されたときの行と列の数を算出
if select == "行"
  puts "行数を入力してください"
  new_line = gets.chomp.to_i # 2次元配列の行数
  new_column = ((input_array.count)/new_line.to_f).ceil # 2次元配列の列数
end

# 2次元配列に変換
i = 0
new_array = []
while i < new_line do
  new_array << input_array[(i*new_column)..(i*new_column + new_column - 1)] # 1次元配列から2次元配列の列数分の要素を取得して空配列に挿入
  i += 1
end

puts "入力した1次元配列"
p input_array

puts "変換された2次元配列"
p new_array
```
流れとしては、以下のようになります。
1. 1次元配列を入力
1. 行数と列数のどちらを固定するのかを選択
1. 行と列、それぞれの場合における行と列の数を算出する
1. 1次元配列から、2次元配列の列数分の要素を取得して、空の配列に挿入する
1. 4の操作を行数分繰り返す

## さいごに
あまりきれいではないかもしれませんが、思いどおりの操作をすることができました。
（そもそも本記事の目的を達成するようなメソッドが既に存在しておりましたら、コメントでご教授いただけると嬉しいです。）
課題8/18-24

・新しいメッセージ、今後の手術予定も真ん中にあるか、それかもっと見るも左によっていくようにしたほうが良さそう。
軸が2つになっている。

・sharedのhooksの登録場所
sharedの特定のコンポーネント依存か、他のコンポーネントにも使うのかによって分ける。

他のコンポーネントにも使うhooksは(例えばログアウト機能など)はshared>hooksの中に入れる。
LinuxをGUI画面にするには

# はじめに
REHL8にOracleDatabase19cをインストールしたく、
REHL8をGUI操作する時にとても苦労したので手順をここに残します。
今回は、xmingというツールを使いました。この記事ではOracleDatabaseのインストールについては触れません。
機会があれば別記事でご紹介したいと思います。

# 環境
- AWS EC2
- REHL8.6 
- Windows10

# 手順

## Windows側の手順
1. 以下からVcXsrvをVダウンロードしてインストール
https://sourceforge.net/projects/vcxsrv/

2.　VcXsrvフォルダを開き、XLaunchアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113544/3ec42971-5649-21da-6464-a64779da4043.png)

3.「Start no dient」にチェックを入れたまま次へをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113544/f3852af4-3ec0-7515-1a31-020cef05b1e8.png)

4. 「Clipboard」にチェックを入れたまま次へをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113544/84db2b87-3147-2064-1845-9dfe05c95a7a.png)

5. そのまま「完了」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113544/9fce721e-008d-defc-82d8-a1e3cf8967cf.png)

6.タスクバーに「Xming 」のアイコンが表示されていると思います。
カーソルを合わせると以下のように「Xming Server0.0」と表示されました。
これでWindows側の準備はOKです。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113544/d6d76a24-4761-0d98-ac50-44f098ba7d7f.png)

## Linux側の手順

1.Teratermの設定です。
設定⇒SSH転送で以下画面を開きます。
「リモートのXアプリケーションをローカルのXサーバに表示する」にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113544/460e165d-50b4-2c8b-bc2c-c0300c42ce6f.png)

2.ファイル⇒新しい接続からEC2のRedhatに接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113544/89b9647f-f0c0-6093-6e24-7baeaf4bc899.png)

3.xorg-x11-xauthとxtermをインストールします。
```
$ sudo yum install xorg-x11-xauth
$ sudo yum install xterm
```


4.ログインしたユーザーから X11 をテストします。
```
$ xauth list
ip-xxx-xx-xxx-xxx.us-west-2.compute.internal/unix:10  MIT-MAGIC-COOKIE-1  e78fb3b67d4def418a70efec323cxxx
```
上記で表示された「ip-xxx～」以降を以下のように「xauth add 」の後に貼り付けて、実行します。
```
$ xauth add ip-xxx-xx-xx-xxx.us-west-2.compute.internal/unix:10  MIT-MAGIC-COOKIE-1  e78fb3b67d4def418a70efec323cxxx

$ export DISPLAY=localhost:10.0

$ echo $DISPLAY
localhost:10.0
```
上記のように「localhost:10.0」が表示されれば準備OKです。

5.試しに、firefoxを起動してみましょう。
しばらくたつと、Windows側のXmingが起動して、firefoxが起動できればOKです。
私の環境では2～3分かかりました。焦らず待ちましょう。
OracleのOUIも同じように起動できるはずです。
```
$firefox &
```

# 最後に
いかがでしたでしょうか。
私は、teratermの 「リモートのXアプリケーションをローカルのXサーバに表示する」にチェックを入れるとエラーになり、
いろいろと試行錯誤してxming起動までに2～3日かかりました。

同じように、teratermで躓いた方がもしいれば、
teratermの「リモートのXアプリケーションをローカルのXサーバに表示する」にチェックを入れて、設定の保存を一度してください。
そのあと、設定⇒設定の読み込みから保存したteratermの設定を読み込み、teratermを起動すると「リモートのXアプリケーションをローカルのXサーバに表示する」にチェックが入った状態で、teratermを起動することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113544/83e6a5b6-b4de-83e9-479f-a031ef9001ca.png)

また、Redhat8ではxeyesがインストールできず、それもハマった点でした。
代わりにxtermで代用可能です。

参考にしていただけると幸いです。
最後までお読みいただきありがとうございました。

# 参考資料
https://dev.classmethod.jp/articles/ec2-x-window/
https://dev.classmethod.jp/articles/wsl-x-window/#toc-6
https://aws.amazon.com/jp/blogs/compute/how-to-enable-x11-forwarding-from-red-hat-enterprise-linux-rhel-amazon-linux-suse-linux-ubuntu-server-to-support-gui-based-installations-from-amazon-ec2/
【#53 エンジニア転職学習】goqueryでスクレイピングした情報をDBに一括保存する

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

 引き続きスクレイピングのプロジェクトをつくっていきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
本日はスクレイピングしてきたURL一覧をDB保存する部分を作成しました。
* **goqueryでスクレイピングしたURL一覧をDBに一括保存する　←Topics!!**


# goqueryでスクレイピングしたURL一覧をDBに一括保存する
昨日作成した、求人詳細へのリンクURL一覧を取得するコードに
MySQLへの一括保存をするコードを追加しました。

一括でINSERTする方法は、結論から言うと「**gorm.CreateメソッドにDBモデルのstructを持つスライスを渡す**」方法になります。
動画ではバルクインサートという手法が紹介されており、
私もバルクインサートになるかは分かりませんが、MySQLへのトランザクションをできるだけ少なくする構成にしました。

手順は以下のようにステップアップしました。
1. goqueryで取得してきたURLを1レコードずつCreateで保存できるか確認
1. 取得してきたURLをDBテーブルモデルのstructを持つスライスに追加する
1. URL一覧が入ったスライスをCreateで一括INSERTする

完成したコードの実行後、MySQLを確認すると
↓ のように同じ時間でINSERTされていることが分かります。
今はレコード数が少ないので体感あまり変わらなかったですが、
レコード数が増えれば実行時間の差が出てくるのだと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2041988/270c01ff-a81e-5953-45b3-247b0434aa69.png)


```main.go
package main

import (
	"job_offer_scraping/db"
	"log"
	"net/http"

	"strings"

	"github.com/PuerkitoBio/goquery"
)

func main() {
	dbconn := db.DbConnect()
	var urllist []db.Mynavi_url

	url := "https://tenshoku.mynavi.jp/list/pg2/"
	res, err := http.Get(url)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
	}

	doc, err := goquery.NewDocumentFromReader(res.Body)
	if err != nil {
		log.Fatal(err)
	}

	doc.Find("div.cassetteRecruit").Each(func(i int, s *goquery.Selection) {
		href, _ := s.Find("p.cassetteRecruit__copy > a").Attr("href")
		href = string([]rune(href))
		url := strings.SplitAfterN(href, "/", 3)
		trimurl := strings.Join(url[0:2], "")

		mynaviurl := db.Mynavi_url{URL: trimurl}
		urllist = append(urllist, mynaviurl)
	})

	dbconn.Create(&urllist)

}
```
```dbmodels.go
package db

import "gorm.io/gorm"

type Mynavi_url struct {
	gorm.Model
	URL string
}
```
```base.go
package db

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func DbConnect() *gorm.DB {
	var dsn = "USER:PASS/job_offer_scraping?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn))
	if err != nil {
		panic("failed connecting DB")
	}
	db.AutoMigrate(&Mynavi_url{})
	return db
}
```

#### 使用している教材はこちら↓

https://www.youtube.com/watch?v=tYbVl6N8oxI&list=PLv6F1QYhG31S-sDkutIQjCnKjFTvjuUus&index=1&t=2049s

# おわりに
最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。
npmについてくるnpxコマンドをもっと活用しようぜ

Node.jsのパッケージマネージャであるnpmには`npm`コマンドのほかに`npx`というコマンドがついてきます。`npx`は便利さのわりにあまり活用されていない気がしたので書いた記事。

# `npx`コマンドとは？🤔
`npx`はnpmのパッケージで定義されたコマンドを起動するコマンドです。npmのパッケージでは`package.json`の`bin`を設定することでそのパッケージをインストールしたときに同時にインストールするコマンドを定義することができます。`npx`ではパッケージ名を指定することでそのパッケージで定義されたコマンドを実行できます。

# 利点1 - ローカルインストールしたパッケージのコマンドの起動が楽😀
npmで配布されているCLIアプリを使うとき、`npm install`に`-g`フラグを付けてグローバルにインストールしろ、という指示になっていることが多いです。

```console:グローバルにインストール
$ npm install -g npm-check-updates
```

これによりコマンドがシステム全体にインストールされるので、パッケージのコマンドがどこからでもそのまま実行できます。

```console:グローバルにインストールしたコマンドを実行
$ ncu
```

しかし、システムにインストールする`npm install -g`には通常`sudo`が必要ですし、システムに変更を加えるのは避けたいです。

だからといってローカルにインストールすると下記のように起動が面倒であるという欠点があります。

```console:ローカルにインストールすると起動が面倒
$ npm install npm-check-updates # ローカルにインストール
$ ./node_modules/.bin/ncu       # 起動
```

そんなときに`npx`を使うと以下のようにローカルにインストールしたコマンドを簡潔に起動できます。

```console:ローカルでも起動が楽！✅
$ npx ncu # 起動
```

単純にパッケージがインストールしたコマンド名の前に`npx`をつけるだけです。

# 利点2 - そもそもインストールしなくて良い😲
前セクションで`npx`を使ってローカルインストールしたパッケージのコマンドを起動する方法を紹介しましたが、実は`npx`ではそもそもパッケージをインストールする必要自体ありません。なぜならインストールされていないパッケージは自動で一時フォルダにインストールして実行するという機能があるからです。

例えば

```console:インストールの必要なし！✅
$ npx npm-check-updates
```

以上だけで`npm-check-updates`パッケージをダウンロードし、一時フォルダに展開し、定義されているコマンドを実行するということを行ってくれます。

他にも静的なウェブサーバのパッケージである`serve`であれば

```console:インストールなしでウェブサーバを直接起動！✅
$ npx serve -p 8080
```

これだけでウェブサーバを起動できます。引数もそのまま渡せます。超便利！
melodicでもopencv-pythonが使いたい（docker）

# はじめに
現在、研究室からお借りしているPCがubuntu18.04でros-melodicを入れています。
ros melodicはpython2系で動いています。

そんな折、どうしてもrosとOpenCV-pythonが使いたくなりました。
OpenCVの最新はもちろんpython3系です。
さっさとubuntu20.04なりにアップグレードしてしまえばいいのですが、どうにかして今の環境で動かしたい。
という事で、dockerにros-noeticを立ててopencvを使い、ローカルな環境のros-melodicと通信しました事についてのまとめ記事です。
## 補足
- OpenCVをビルドしてpython2系でも使えるそうですが、なんか上手くいきませんでした。
- ros-melodicでもpython3は動きますが、色々面倒そうなので使っていません。
# 構成
- ubuntu18.04
    - ros-melodic
    - docker
        - ros-noetic
        - opencv-python
# やり方
## docker側
まずはdockerのros-noeticで、mypkgというパッケージのmypkg.pyノードを動かす環境を作ります。
mypkg.pyでopencv-pythonをインポートする事を想定しています。

以下に示すDockerfileとdocker-compose.ymlを、このツリーのように配置してください。
```bash
mypkg/
├── CMakeLists.txt
├── Dockerfile
├── docker-compose.yml
├── package.xml
├── script
│   └── mypkg.py
└── src
```
配置が出来たら、ターミナルから以下を打ちましょう。
```
$ docker compose up -d
$ docker exec -it ros-noetic bash
```
ros-noeticが起動したら、catkin_makeをして、bashを打てばパッケージが動かせます。
### Dockerfile
```Dockerfile
# osrfが提供するrosイメージ（タグがnoetic-desktop-full）をベースとしてダウンロード
FROM osrf/ros:noetic-desktop-full

# Docker実行してシェルに入ったときの初期ディレクトリ（ワークディレクトリ）の設定
WORKDIR /root/

# ROSのセットアップシェルスクリプトを.bashrcファイルに追記
RUN echo "source /opt/ros/noetic/setup.sh" >> .bashrc
RUN echo "source /root/catkin_ws/devel/setup.bash" >> .bashrc

# OpenCVのインストール
RUN apt-get update
RUN apt-get install -y python3-pip
RUN python3 -m pip install opencv-python
RUN apt-get install -y ros-noetic-cv-bridge

ENTRYPOINT [ "bash" ]
```
### docker-compose.yml
```yaml
# versionはdocker composeのversionに合わせる
version: '3.8'

services:
  ros:
    container_name: ros-noetic
    # ttyを入れないとすぐに終了する
    tty: true
    build:
      dockerfile: Dockerfile
      context: .
    network_mode: "host"
    volumes:
      - type: bind
        source: .
        target: /root/catkin_ws/src/mypkg
    # environment:
    #  ROS_MASTER_URI: http://172.17.0.1:11311
    #  ROS_IP: 172.17.0.1
    #  ROS_HOSTNAME: 172.17.0.1
```
## ローカル側
ローカルのros-melodicを、dockerのros-noeticと通信します。
~~環境変数を変更するだけです。~~
dockerのnetworkにhostが設定されていたら大丈夫（変更）

<details><summary>昔やっていたこと</summary><div>

ターミナルで
```
export ROS_MASTER_URI=http://172.17.0.1:11311
export ROS_IP=172.17.0.1
export ROS_HOSTNAME=172.17.0.1
```
以上で完了です。
同じ環境変数がdockerのros-noeticにも設定されています。
あとはどちらでroscoreをしても、お互いに接続可能です。

</div></details>

# 参考
https://qiita.com/Yuya-Shimizu/items/3d9fc18f42aee40f23b3

https://zenn.dev/suzuki_hoge/books/2022-03-docker-practice-8ae36c33424b59

https://qiita.com/tomoyafujita/items/07937a25bc48aa076056
40代おっさんデータモデルを学ぶ②

## 本記事について

この記事はプログラミング初学者の私が学んでいく中でわからない単語や概要を分かりやすくまとめたものです。
もし不正などありましたらコメントにてお知らせいただければ幸いです。

## 概念・論理・物理データモデル

物理モデル：データベースに実装する姿を描いたもの
論理モデル：システムの用件定義や基本設計、外部設計に対応し、エンティティに属性を当て込んでキーを定義する。すべての必要な属性を定義したものが論理モデルとなる。
概念モデル：一番最初にビジネスの世界をとらえるもので、ビジネスの実態もとらえるのに必要なエンティティを定義して、それらの関係を表したもの

## トップダウンとボトムアップアプローチ

トップダウン：上から業務全体を見渡してエンティティをとらえて作っていく
ボトムアップ：現行システムの画面や帳票、あるいは台帳などからデータを抽出してエンティティにモデルを作る

## データカタログ

実データとセットでデータモデルでは表現・説明しきれないことを記述した辞書

## モデリングの定石（基本作法）

・一意性の選別
・ロールの割り当て
・汎化・特化
・ｎ：ｍ関係の１：ｎ関係への帰着（多対多関係の１体N関係への帰着）
・実態の見極め

### 一意性の選別

エンティティ上の主キーに何を選定するかと言うこと

例えば
社員：入社時に社員番号が振られる

＊複数の項目がセットで一意となる場合もある

### ロールの割り当て

日本語で言うと役割の概念

### 汎化・特化

特化：どんどん分類していくこと、あるいはサブタイプ化ともいう
汎化：スーパータイプ

### ｎ：ｍ関係の１：ｎ関係への帰着

多対多関係の１体N関係への帰着

例えば
二つの会社に属しているNさんがいたとしたら
所属と言うエンティティを置くことで解決することができる

### 実態の見極め

エンティティの見極め
エンティティをどのように抽出し、定義をしていくかということ

## 参考資料

udemy講座　ビジネス推進のためのデータモデリング入門を参考にしました。
CSSのcalcの乗算除算の罠

CSSには`calc`といってプロパティ値に入れる数値をCSS側だけで計算できる仕組みがある。
```css
.apple{
    width: calc( 100vw - 50px );
}
```
この`calc`は四則演算は使えるのだが、実は乗算と除算では気を付けないといけないことがある。
それは乗算と除算では単位付きの計算で制限がある。

https://developer.mozilla.org/ja/docs/Web/CSS/calc

上にあるように乗算では片方のみが単位付きを認められていて、
除算では左側(分子)のみが単位付きなのが認められている。

(正確に言うともう片方がnumeric型でなければいけない。)

```css
.bad-apple{
    /* 　設定されない */
    width: calc( 10px * 10px );
    height: calc( 100px / 10px );
}
.orange{
    /* 　設定される */
    width: calc( 10px * 10 );
    height: calc( 100px / 10 );
}
```

まあ$px*px$が${px}^2$ だったり$px/px$は無単位だから単位が変わるというのもわかるが、
だったら$px/px$を単なる無単位量なnumeric型にしてくれたらよかったのだが…。

https://triple-underscore.github.io/css-values-ja.html

を見ると具体的な単位などが見ることができる。また型の決定方法も[ここ](https://triple-underscore.github.io/css-values-ja.html#calc-type-checking)に書いてある。
C++でRaw画像を読み込んで、そのまま出力する

# 取り組んだこと  
C++でRaw画像を読み込んで、そのまま出力することに取り組んだ。  
勉強のためにスマートポインタも使ってみた。  

# コード  

```C++:main.cpp
#include <iostream>
#include <string>
#include <fstream>


#define X_SIZE 768
#define Y_SIZE 576
#define CH 3

std::string input_name = "dog.raw";
std::string output_name = "dog_out.raw";


int main(void) {
	
	std::unique_ptr<unsigned char[]> input_image=std::make_unique<unsigned char[]>(X_SIZE * Y_SIZE * CH);
	std::unique_ptr<unsigned char[]> output_image=std::make_unique<unsigned char[]>(X_SIZE * Y_SIZE * CH);

	// 画像読み込み
	std::ifstream fin(input_name.c_str(), std::ios::in | std::ios::binary );

	if (!fin){
		std::cout << "ファイル が開けません"<<std::endl;
		return 1;
    }

	fin.read(reinterpret_cast<char*>(input_image.get()), X_SIZE * Y_SIZE * CH);

	// 画像書き込み
	for (int y = 0; y < Y_SIZE; y++) {
		for (int x = 0; x < X_SIZE; x++) {
			for (int ch = 0; ch < CH; ch++) {
				output_image[(y*X_SIZE + x)*CH + ch] = input_image[(y*X_SIZE + x)*CH + ch];
			}
		}
	}

    std::ofstream fout;
    fout.open(output_name.c_str(), std::ios::out|std::ios::binary);

	fout.write(reinterpret_cast<char*>(output_image.get()), X_SIZE * Y_SIZE * CH);


	fin.close();
	fout.close();

	return 0;
}
```
# 使用画像  
以下の画像をimage JでRawに直したもの。
![dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077648/1c9feaa7-ef87-724a-d317-c393153d4d2b.jpeg)
RubyInstaller 3.1.2-1はまずgem install bundlerしましょう

言いたいことはタイトルで完了したので以下発生した問題と原因・解決方法です。

# 問題：rails newが通らない

ちょいと検証したいことがあって`rails new`しようと思い、devkitなしのバージョン入れてたことに気づいて（ネイティブライブラリビルドするgemがインストールエラーになって）、ついでなのでRubyInstallerでRuby 3.1.2を入れました。

で、`rails new`したところ、`bundle install`は通ったもののその後の処理でエラーが出てしまいました。

```
       rails  importmap:install
rails aborted!
TZInfo::DataSourceNotFound: tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install
C:/TEMP/sample_app/config/environment.rb:5:in `<main>'

Caused by:
TZInfo::DataSources::ZoneinfoDirectoryNotFound: None of the paths included in TZInfo::DataSources::ZoneinfoDataSource.search_path are valid zoneinfo directories.
C:/TEMP/sample_app/config/environment.rb:5:in `<main>'
Tasks: TOP => app:template => environment
(See full trace by running task with --trace)
       rails  turbo:install stimulus:install
You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem.
You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem.
```

tzinfo-dataが入ってない？そんなわけないやろと思いましたが、そんなわけありました。ちなみにtzinfo-dataをインストールするためのGemfileの記述は以下のようになっています。

```rb:Gemfile抜粋
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]
```

# 原因その1：platform文字列の変更

実はRubyInstallerは3.1.0から[UCRT](https://docs.microsoft.com/ja-jp/cpp/porting/upgrade-your-code-to-the-universal-crt?view=msvc-170)を使うようになっており、platform文字列が**x64-mingw-ucrt**に変更されています。

https://rubyinstaller.org/2021/12/31/rubyinstaller-3.1.0-1-released.html

「x64-mingw」の個所だけ見てマッチしてくれそうですがそうは問屋が卸しませんでした。

# 原因その2：Ruby 3.1.2同梱のbundlerではx64-mingw-ucrtに未対応

同梱されているbundlerは2.3.7です。というわけで2.3.7の「platformはx64_mingwかい？」と調べている箇所を見てみましょう。ってrubygemsの下に移動したからbundlerのバージョンを固定してみる方法がわからん。ともかく問題の部分です。

https://github.com/rubygems/rubygems/blob/0fdd9f0882bb74506b3b5e292051000335f282c9/bundler/lib/bundler/current_ruby.rb#L79-L81

```rb:bundler/current_ruby.rb
    def x64_mingw?
      Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64"
    end
```

おわかりいただけただろうか。
"mingw32"と等価比較をしているのである！
というわけで「x64-mingwの部分だけ見てるんちゃうん？」という疑問については、「ちゃいまっせー」でした。昔誰かが「プログラムは期待するようには動かない。書いてある通りに動く」って言ってた気がします。

余談ですが、「x64」で「mingw32」っての変だよなーとはずっと思ってたのですが互換性のため？に「mingw32」としていたのを今回思い切って32をなくした？ら影響があったってプログラミングあるあるな感じですね:scream:

# 解決方法

さてわざわざ問題があるコードを先に見せたことからわかると思いますが、最新版ではちゃんと直ってます。
って、6/29って、3.1リリースしてから半年も経ってるやん。ひょっとして誰もWindowsでRails開発してない？（私はしてます）

https://github.com/rubygems/rubygems/commit/86ecdd0160a6c2cd48eb397d2cd1ebb15228ba21

タイトルに書いたようにbundler自体を更新しましょう。

```
>gem install bundler
Fetching bundler-2.3.20.gem
Successfully installed bundler-2.3.20
Parsing documentation for bundler-2.3.20
Installing ri documentation for bundler-2.3.20
Done installing documentation for bundler after 0 seconds
1 gem installed

>bundler -v
Bundler version 2.3.20
```

今度は先ほどのエラーが起こることなく`rails new`が完了します。
wsl2のディスクサイズ最適化

自分用まとめ。

`optimize-vhd`コマンドが使えない人向け。（おそらくHyper-V関連をインストせずWSL2？Docker？を利用しているからと思われる）

## vhdxファイルのパスを調べる

PowerShellを起動し以下のコマンド実行。（WSL2でUbuntuを利用の場合）
`PackageFamilyName`の値をメモ。

```
> Get-AppxPackage -Name "*Ubuntu*"

Name              : CanonicalGroupLimited.Ubuntu20.04onWindows
Publisher         : CN=23596F84-C3EA-4CD8-A7DF-550DCE37BCD0
Architecture      : X64
ResourceId        :
Version           : 2004.2021.825.0
PackageFullName   : CanonicalGroupLimited.Ubuntu20.04onWindows_2004.2021.825.0_x64__79rhkp1fndgsc
InstallLocation   : C:\Program Files\WindowsApps\CanonicalGroupLimited.Ubuntu20.04onWindows_2004.2021.825.0_x64__79rhkp
                    1fndgsc
IsFramework       : False
PackageFamilyName : CanonicalGroupLimited.Ubuntu20.04onWindows_79rhkp1fndgsc
PublisherId       : 79rhkp1fndgsc
IsResourcePackage : False
IsBundle          : False
IsDevelopmentMode : False
NonRemovable      : False
Dependencies      : {CanonicalGroupLimited.Ubuntu20.04onWindows_2004.2021.825.0_neutral_split.scale-150_79rhkp1fndgsc,
                    CanonicalGroupLimited.Ubuntu20.04onWindows_2004.2021.825.0_neutral_split.scale-100_79rhkp1fndgsc, C
                    anonicalGroupLimited.Ubuntu20.04onWindows_2004.2021.825.0_neutral_split.scale-125_79rhkp1fndgsc}
IsPartiallyStaged : False
SignatureKind     : Store
Status            : Ok
```

`PackageFamilyName`の値をもとにエクスプローラなどで次のディレクトリを確認。

```
C:\Users\{ユーザ名}\AppData\Local\Packages\{PackageFamilyName}\LocalState\ext4.vhdx
```

## 最適化実施（DISKPART利用）

### 1.PowerShellでWSLを止める

```
> wsl --shutdown
```
### 2. diskpartの操作

PowerShellでdiskpartを起動する（コマンドプロンプトが別途起動）
※Docker DesktopなどWSL上で動いている物があれば、予め停止しておく。

```
> diskpart

# ここから別に起動したコマンドプロンプト
> select vdisk file="C:\Users\{ユーザ名}\AppData\Local\Packages\{PackageFamilyName}\LocalState\ext4.vhdx"

DiskPart により、仮想ディスク ファイルが選択されました。

> attach vdisk readonly

  100% 完了しました

DiskPart により、仮想ディスク ファイルがアタッチされました。

> compact vdisk

  100% 完了しました

DiskPart により、仮想ディスク ファイルは正常に圧縮されました。

> detach vdisk

DiskPart により、仮想ディスク ファイルがデタッチされました。

> exit
```

### 3. WSL起動

PowerShellでディストリビューションの確認
```
> wsl -l
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu-20.04 (既定)
docker-desktop-data
docker-desktop
```
ディストリビューションの実行
```
> wsl -d Ubuntu-20.04
```
VBA でステップ実行中、勝手に Function プロシージャに制御が移る現象とその対処

# はじめに
ワークシートにユーザー定義関数（Fuction プロシージャ）を含むシートをコピーするような VBA をステップ実行でデバッグするとき、シートに含まれる Function プロシージャを1セルごとにステップ実行してしまうため制御が移ったままになり、デバッグが困難になってしまう。
原因は、数式計算が自動になっているとき、ステップ実行中に再計算を行ってしまい、再計算するたびに Function プロシージャが実行されてしまうためだと考えている。
そこで、一時的に数式計算を手動とし再計算を行わないようにすることで、Function プロシージャが再実行を抑制し、デバッグを容易にすることができると考えた。

おそらく、こちらのフォーラムも同じ状況だと思われる。
[Microsoft コミュニティ - Excel2010でステップインを実行中に、Functionプロシージャへ勝手に制御が移ってしまう](https://answers.microsoft.com/ja-jp/msoffice/forum/all/excel2010%E3%81%A7%E3%82%B9%E3%83%86%E3%83%83/97bcdbe0-135e-4592-8b7a-73f42a8bbdfd)

# 対処方法
## 1: 一時的に計算方法を手動にする
デバッグ時に計算方法が自動になっていることが今回の原因であるため、デバッグ前に計算方法を手動に設定することで防ぐことができる。
ただし、計算方法の設定が他のバグに影響する可能性や、設定を戻し忘れてしまう可能性もある。

## 2: VBAのコードで計算方法を手動にする
シートの再計算が予想されるコードの直前で計算方法を手動とし、直後に自動に戻すことで対処できる。
```vb
' ワークシートで利用するユーザー定義関数
Function TestFunc(val1, val2)
  TestFunc = val1 + val2
End Function

' ステップ実行でデバッグしたいプロシージャ
Sub CopySheet()
  ' 数式計算を手動化
  Application.Calculation = xlManual
  
  ' シートの再計算が予想されるコード
  ActiveSheet.Copy After:=ActiveSheet
  ActiveSheet.Name = "複製されたシート"
  
  ' 数式計算を自動化し、再計算
  Application.Calculation = xlAutomatic
  Calculate  ' F5で継続実行する
End Sub
```

# 現象の再現方法
Windows 版 Excel 2016 にて動作確認を行っています。

## 1: VBA コードの記述
新しいブックを作成し、標準モジュールに次のコードを記述する。
```vb
' ワークシートで利用するユーザー定義関数
Function TestFunc(val1, val2)
  TestFunc = val1 + val2
End Function

' ステップ実行でデバッグしたいプロシージャ
Sub CopySheet()
  ActiveSheet.Copy After:=ActiveSheet
  ActiveSheet.Name = "複製されたシート"
End Sub
```

## 2: ワークシートでのユーザー定義関数の利用
ワークシートにユーザー定義関数（Function プロシージャ）を利用したセルを用意する。

次の画像のように作成する。黄色に塗りつぶされたセルに TestFunc プロシージャが利用されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/e933d68e-38e7-b1d9-5a1a-38533ecffcff.png)

ちなみに、「数式の表示」が有効な状態では次のように表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/6f45d55e-9fd7-ab3f-2ad8-8d638d27da73.png)

## 3: Excel の設定
"数式"リボンの中の"計算方法"グループの中の"計算方法の設定"を、"自動"に設定する。初期設定では自動になっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/3fd50b72-5e70-c7a7-1705-7ad13a7726c4.png)

## 4: デバッグにて現象再現
CopySheet プロシージャを実行する。
通常通りの実行（F5）では特に問題は出てこないが、デバッグのためステップ実行（F8）をすると、デバッグしたい CopySheet プロシージャではなく、TestFuncプロシージャばかりをステップ実行してしまい、なかなか `ActiveSheet.Name = "複製されたシート"` のコードを確認できない。

# さいごに
他にも良い対処方法がないか Google 検索しましたが、私の力では見つかりませんでした。もっと他に良い方法があれば教えてください！
また、こちらの現象は、[FOM出版の「よくわかる Microsoft Excel 2019/2016/2013 マクロ/VBA」](https://www.fom.fujitsu.com/goods/excel/fpt1910.html)で VBA を勉強している、ほかの人から質問されて遭遇したものです。VBA の自習に良い本なのでオススメです。
さらに付け加えると、そもそも Function プロシージャをワークシートから呼び出すのはやめた方がよいと思いました。マクロを有効にしないと再計算できないし。
CKADに合格したので体験記を書いてみた

# はじめに
2022/8にCKADを受験して合格しました。
2022/6に試験の方法が変わったりしていて、今までの情報が役に立たなかったりするので、その辺も含めてお伝え出来ればいいなぁと思ってます。

# 試験の内容
問題文にあるリソースを作成したり、すでにリソースはあるけど上手く動作しないから解決してください、といった内容になります。
実際に画面上でコマンドを打って解くので、実務に生きやすいかもしれません。

# 前提知識
kubernetesは勉強を始める前に少しだけ触ったことがある程度で、ほとんどの内容を知らない状態でした。

# 難易度
比較する対象として合っているかは分かりませんが、AWS Certified Solutions Architect - Associate くらいの難しさかな？と思います。
ただ、実際にリソースを作成するので焦ってコマンドミスとかある分心理的ハードルが少し高め。

あと試験の内容をちょこちょこ調べる中で「前提の知識がどれくらいで、期間どれくらいあれば合格出来るんや！」ってなったのでそれも書いておきます。
自分は勉強を始めてちょうど二か月で合格出来ました。

# 勉強方法
みんな大好きUdemyで勉強しました。その他はほとんどやってません。（勉強量としては4週くらいしたかな？）
動画を見て、確認テストをする形式になります。 **いちいち自分で環境を用意しなくていいのが何より嬉しい！**
実際のテストさながらに画面を使って問題を解くので、慣れという意味でもかなり効きましたね！
この中に出てくるテストの難易度自体も本番とかなり似通っていたんじゃないかなと。
Litning Labははっきり言って試験以上の内容なので、 **ぶっちゃけやらなくても大丈夫です。** <BR>
~~あと日本語字幕はないですが、リソースの動きなどをしっかり図示してくれるので、そこを見ればなんとなく分かります。~~
~~僕自身英語は全然できません。~~
最近日本語字幕が追加されました。機械翻訳なのでたまにエキサイトしますが、図解もあるので勉強する分には問題ないかと。

https://www.udemy.com/course/certified-kubernetes-application-developer/

セール中だと4000円以下くらいだった気がするので、セールで買うべし！

上記に加えて、受験申し込みをした際に、二回分の模擬試験が公式で出来るようになっているので、上記が一通り終わったらやってみてください！
「実際の試験より難しいよ」と書いてますが、実際に **本番の2倍くらいタスクが多く設定されている** ので、時間内に解けなくても全然問題ありません。
一回目は半分くらいしか解けなかったです。

# 試験で使ったテクニック
よく使うコマンドはまとめておくと楽になります。
ちなみにこの辺のコマンドは試験Tipsとして公式のサイトにも乗っているので是非覚えてください！
```
alias k=kubectl
export dry = --dry-run client -o yaml
```

ちなみにコンテキストの切り替えはコマンドを全て公式が問題文の中に用意してくれています。

# 受験方法
自分は下記から申し込みました。
英語が出来るならJPの付いていないお安い方で受けることも可能です。

https://training.linuxfoundation.org/ja/certification/certified-kubernetes-application-developer-ckad-jp/

当日は他のリモート試験と同じく、「政府発行の身分証明書を提示」し、「部屋の中の様子全体をカメラに映す」ように指示されます。
壁、天井、机回り、机の下、キーボードの下を **かなりゆっくり写さないと怒られます。**
僕の場合、背後に段ボールを割と積んでいたりしましたが、それは特に何も言われませんでした。

机の上は身分証明書、マウス、キーボード以外はないようにしました。（ラベルのないペットボトルの水は許されるようです）

# 2022/6で大きく変わったこと
「Chromeの中にkubernetes.ioのブックマークを事前に仕込んでおくと楽！」と書いてある記事がちらほらありますが、6月の改定から **一切意味がなくなりました。**
自前のブラウザではなく、 **PSI Bridge Secure Browser** というものを使うように変わったためです。
このブラウザ内ではFireFoxを使って検索することになります。
関係のないサイトに接続出来なくなっているので、間違ってアクセスするという事故は減ったと言えるかもしれません。

また、上記を使用する影響で **デュアルモニターが使えなくなりました。**
調べ物を片方でやりながらもう片方の画面で問題を解く、は出来ません。

# おわりに
直近で受けて、「これは事前に知っておきたかったな！」というのは書けたかな？と思います。
そういえばこれもあったな、とかあれば更新していきます。
他に「こういうのが知りたい！」等コメントいただければ反映していこうかと。

少しでもお役に立てたなら嬉しい限りです！
「楽しくなければ仕事じゃない」干場 弓子＜エンジニア夏休み企画>【読書感想文】

エンジニア夏休み企画  読書感想文 
https://qiita.com/official-events/6d31965c499a69377c0b

参加記事です。　

 <この項は書きかけです。順次追記します。>
#  楽しくなければ仕事じゃない　
干場 弓子
https://bookmeter.com/books/14508555
https://booklog.jp/item/1/B07YTPZWBH
https://www.amazon.co.jp/dp/product/4492046577/

>「楽しい仕事はあるが、楽な仕事はない」本田宗一郎の言葉を仕事場に掲げているという。お客様に対して、世界一のものが提供できなくて、お金を貰おうという人には、必ず後ろめたいことがあり、楽しく仕事はできるはずはない。世界一を提供しようと思ったら楽はできない。あたりまえのことを、さりげなく書いているところがよい。 気になるところといえば、文章表現で言いたいことはある。趣味の問題だし、直接本人に言うことにする。読者の方が、文章表現で気になるところがあれば、そっと教えていただけると幸いです。

# 読者の応用例　
著者にばかり応用例を求めるのではなく、自分の応用例を書くのも、読書感想文としてありだと思う。

## 個人開発　
個人開発の魅力は、つまらない上司がいないことかもしれない。　
あるいは、つまらない同僚でもよい。　
仕事を手伝うのではなく、なにかと文句をつける。　

プログラマの「日報、週報、月報、年報」考。仮説(73)
https://qiita.com/kaizen_nagoya/items/97ad8ac9217c12c3bb69


## 箱庭　

箱庭もくもく会 #10 日時：2022/09/14(水) 17:30-19:30
https://hakoniwa.connpass.com/event/258129/

箱庭プロジェクトをなぜこんなに推しているかといえば、二つある。　

ひとつは、問題解決能力の高さが伝染してくることを期待して。　

問題解決能力の高い人と仕事をしていると、自分もときどき同じような発想になれることがあるような気がする。（気がするだけのこともしばしばある）　　

日本のプログラマが世界で戦える16分野・事例。仮説（53）統計と確率(25)
https://qiita.com/kaizen_nagoya/items/a7e634a996cdd02bc53b

仮想戦略会議「箱庭」
https://qiita.com/kaizen_nagoya/items/73cb132707653176a461

お盆には「箱庭」記事を書きましょう「もくもく会」の題材になる（１）
https://qiita.com/kaizen_nagoya/items/a22bf2b1dab0ad3258d4

お盆には「箱庭」記事を書きましょう「もくもく会」の題材になる（2）
https://qiita.com/kaizen_nagoya/items/e3c0ceb2dcc9cf3f3fac

# 参考資料　

著者が出版社時代に、出版社側として出された本。

トリーズ(TRIZ)の発明原理40 あらゆる問題解決に使える[科学的]思考支援ツール
高木芳徳
https://bookmeter.com/books/8217532


「人生で影響を受けた本100冊」に28冊足す計画（14冊）
https://qiita.com/kaizen_nagoya/items/3ae6633725df77261df8

著者があらたに始めた出版事業に、出版側として出された本。

「科学的論理思考のレッスン」高木敏行 , 荒川哲＜エンジニア夏休み企画>【読書感想文】
https://qiita.com/kaizen_nagoya/items/b7090bca722c5a4a66b9

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20220818
ver. 0.02 「科学的論理思考のレッスン」高木敏行 , 荒川哲＜エンジニア夏休み企画>【読書感想文】URL追記 20220829

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
[OutSystems]Timerの実行状況を(System)のEntityを検索して知る

Timerの実行状況はService Centerで確認できる（モジュールページのTimersタブや、Monitoring > Timersページで）。(System)から参照できるEntityを検索することで同じことができるのでその方法をメモ。

# 環境
Personal Environment(Version 11.16.0 (Build 35766))
Service Studio(Version 11.53.11)

# サンプルモジュール
[Forgeコンポーネント](https://www.outsystems.com/forge/component-overview/7086/housesoftsamplereactive)のV1.0.9。
MainFlow > TimerEntity Screen

# ドキュメント
[Timer](https://success.outsystems.com/Documentation/11/Reference/OutSystems_Language/Processes/Timer)
日本語版のページもあるが、2022/08/17時点では中身がほぼ空なので、英語版を確認する必要がある。

# Entity
以下のEntityについては、今回必要な部分のみに言及。
その他の情報については、ドキュメントの項に貼ったリンク先を参照。
## Meta_Cyclic_Job
Timerの定義を格納するEntity。
その環境における、該当Timerの設定値（実行スケジュール等）も持っているが、ここでは以下の属性だけを確認する
- Id属性：実行情報を持つCyclic_Job_Sharedを検索するための属性
- Espace_Id属性：Timerが作られたeSpaceのId。Built-In FunctionのGetEntryEspaceId()を使ったり、Service Centerで該当eSpaceのページを開き、そのクエリストリングから取得できる
- Name属性：Timerの名前

## Cyclic_Job_Shared
Timerの実行情報を格納するEntity。マルチテナントでないものに限る。マルチテナントのTimerは
Cyclic_Jobという別のEntityにある。
Meta_Cyclic_Job Identifier型の属性が主キーなので、TimerがあるeSpaceのIdとTimer名でMeta_Cyclic_Jobを検索し、そのIdをこのEntity検索に使えば1レコードだけ取得できる。
- Is_Running_Since属性：Date Time型。実行中にのみ、開始日時が設定される。よってこの属性が設定されているときはTimer実行中と判定できる
- Number_Of_Tries属性：何回目の試行か。Timerは、エラー発生時に環境ごとに定められた回数（デフォルト3回）を上限としてリトライが行われる。
- Last_Run属性：Date Time型。最後のTimer実行が開始した日時。エラー発生してリトライするときは、最後のリトライの開始日時が設定される（1回目ではない）

# サンプル実装
Aggregateを使い、特定のTimerのステータスを取得する方法。
## 参照追加
(System)の下にあるMeta_Cyclic_JobとCyclic_Job_Sharedへの参照を追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/dd15a9dd-c11d-53ea-bba9-a76d8684812c.png)

## Aggregate
Sourcesタブ。Meta_Cyclic_Job Identifier型の属性同士でジョインしている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/8d9d9453-c111-98b4-3771-5ac088285701.png)

以下の条件は、同じeSpace内にあるDummyTimerという名前のTimerを検索するときの条件。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/0567851f-edd4-acc2-8215-d2237dbee49f.png)

## サンプルの実行イメージ
起動ボタンをクリックすると、同じeSpace内のDummyTimerというTimerを実行する。
確認ボタンをクリックすると、その時点のDummyTimerの実行状態をEntityから検索して幼児する。
②の行の右側に、Is_Running_SinceとNumber_of_Tries属性の値を表示。
③の行の右側に、Last_Run属性を表示。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/d8eb27a7-8176-d481-b065-c883ae607374.png)
JavaScriptのPromiseについて part3

# 初めに
今回は`async`と`await`キーワードについてまとめていきたいと思います。

参考文章はこちらです。
[Async/await - javascript.info](https://javascript.info/async-await)

# `async`/`await`
`async`：関数が解決（resolve）された`Promise`を返すことが約束される。
`await`：`async`関数の中で、指定の`Promise`が完了（settled）状態になるまで待つ。`async function`の中のみ動作する。

## `await`
`await`の動きを見ていきたいと思います。
```jsx
async function fn() {
  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve('done!'), 1000)
  })

  let result = await promise

  console.log('before result')
  console.log(result)
  console.log('after result')
}

fn()
console.log('after fn')


// after fn

// before result
// done!
// after result
```
`async`関数`fn`を呼び出したあと`console.log('after fn')`が実行し、`fn`に戻って`await`が変数`promise`の`setTimeout()`が`resolve()`を返すまで待ち、最後に残りの部分が同期に実行していきます。

`await`と`setTimeout()`、`resolve()`併用すれば結果の出す時間が計測器でちゃんと作動し、`await`で必ず結果を得てから後の処理を継続していく。`async`も`await`もとても便利でわかりやすく使うキーワードだと思います。

しかしテストの中ちょっと気になるところまた出てきましたので、
例えば、**`await`をつけた`Promise`は`Promise`オブジェクトとして使えるでしょうか。**
```jsx
async function test() {
  let promise = await new Promise((resolve, reject) => {
    setTimeout(() => resolve('123'), 3000)
  })

  promise.then((result) => {
    console.log(result)
  })
}

test()

// UnhandledPromiseRejectionWarning: TypeError: promise.then is not a function
```
実行すると未処理エラーが出てました。あれと思って、
```jsx
async function test() {
  let promise = await new Promise((resolve, reject) => {
    setTimeout(() => resolve('123'), 3000)
  })

  // promise.then((result) => {
  //   console.log(result)
  // })
  console.log(typeof promise) // string
  console.log(promise instanceof Promise) // false
  console.log(promise.toString()) // 123
}

test()
```
`await`を外すとこうなるんですが、
```jsx
  console.log(typeof promise) // object
  console.log(promise instanceof Promise) // true
  console.log(promise.toString()) // [object Promise]
```
そして`Promise.resolve()`を使って、`then`が正常に動作してくれました。
```jsx
  Promise.resolve(promise)
    .then((result) => {
      console.log(result) // 123
    })
```
もちろん`async`なら、関数`test`が返された結果を`Promise`でラップし、`then`でその結果を受け取り、進んでいきます。
```jsx
async function test() {
  let promise = await new Promise((resolve, reject) => {
    setTimeout(() => resolve('123'), 3000)
  })
  return promise
}

test()
  .then(result => console.log(result)) // 123
```
下は`async`をつけた関数の検定です。
```jsx
console.log(test().toString()) // [object Promise]
console.log(test() instanceof Promise) //true
```
STM32G031J6M6用の俺の考えた最強の「hello...」(PA_2シリアル出力)(mbed-os)(STM32)


x 超超重要 なぜか秋月STM32G031J6M6がうり切れていた。注意!!(2022/8/27現在)

x 過去ログを見よ
x PA_2をOBでGPIOに出来る人むけ
x STM32G031は、秋月で売っているSTM32G031J6M6の事

目的
シリアルのテスト
mbed-osのシリアルをソースを見ていたら
PA_2,PA_3が有効なので作ってみた。


![o_con683.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/678fcdc8-c206-5f61-2bd2-da4026abc04f.jpeg)

![o_con684.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/19160217-d265-6f22-a0d6-e29ed88d421c.jpeg)

![o_con685.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/9f1d52d3-50ad-6961-f438-742d446c578b.jpeg)

![o_con686.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3b9bf8f5-4202-5c79-5078-9fca09a73e01.jpeg)

![o_con687.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/cc5caf80-65e3-5cfb-4c88-cbe72945fb4f.jpeg)



```c++



//ser_test_1_031_1

#include "mbed.h"

//シリアルの定義
UnbufferedSerial serial_port(PA_2, PA_3); //031

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

    //シリアルの初期化
    serial_port.baud(9600);
    serial_port.format(
        /* bits */ 8,
        /* parity */ SerialBase::None,
        /* stop bit */ 1
    );

    char data_read[256];  //バッファー

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

        //文字列の表示
        //                 12345678901
        serial_port.write("hello world\r\n", 11+2);

        //数値の表示
        sprintf( data_read, "%d\r\n", 1234 );
        serial_port.write(data_read, 4+2);

        //1秒待つ
        wait_us(1000*1000);

    } //while

} //main




```
40代おっさんデータモデルを学ぶ

## 本記事について

この記事はプログラミング初学者の私が学んでいく中でわからない単語や概要を分かりやすくまとめたものです。
もし不正などありましたらコメントにてお知らせいただければ幸いです。

## モデリングとは

現実の業務の世界を抽象化して図式表現すること

★業務の世界：販売管理、在庫管理、購買管理など
★システムの対象を定まった記法で図式表現したもの
　（産能式業務フロー、UML、BPMN、ERD、フローチャート）
★現実の正解を写像したもの

### ビジネスの世界は以下の3つの要素でモデル化できる

業務機能：受注する、在庫管理する、配送する、請求するなど
データ：顧客、商品、受注、在庫、配送、請求
プロセス：データと業務機能を結び付けた仕事の流れ、ワークフロー

## データモデルとは

・ビジネスの実態や業務ルールをエンティティ、属性、リレーションシップで表したもの
・物事を抽象化して捉えたもの：汎化特化
・物事を分類体系化したもの：サブタイプ
・インスタンスをメタ化して表したもの：データカタログ
・データベース設計の全工程として作成するもの

## データ中心とは

データ中心という考え方

データはプロセス（プログラム）より安定している。
プロセスは経年変化していくが、データは企業がある限り存続していく。

上のようなことがわかるので
ビジネス上のデータに着目してビジネスプロセスを考えよう。
データを活用して経営に活用していこう。
という考え方

## 4W1H

Who: だれが
When: いつ
What:　何を
Where: どこで
How: どのように

## データモデル要素

基本要素：エンティティ、リレーションシップ、属性

エンティティ
独立エンティティ：他のエンティティの存在にかかわらず存在し得るモノ
従属エンティティ：上位（親）のエンティティの存在があって初めて存在するモノ

リレーションシップ
分類（サブタイプ）
依存関係
非依存関係

属性：エンティティを保管して説明するモノ
キー属性：エンティティ内のインスタンスを市井にする属性、主キーともいう。
非キー属性：キー以外の属性、主キーが定まれば定まる。

## 参考資料

udemy講座　ビジネス推進のためのデータモデリング入門を参考にしました。