OmniAICreator/Qiita-1.07M huggingface dataset:
RDBMSとSQLについて

#目的
入門 Python3をやっていて8.4 RDBMS の理解が浅くSQLに関して勉強しても頭に入ってこなかったため、体系的に理解したくまとめる。

#そもそもデータベースとは?
- ビジネスの活動の中でデータ(事実)を蓄積し、そのデータを情報としての価値を最大限に活かせるようにするための道具、またはインフラ基盤。

##データベース・マネジメント・システム(DBMS)
複数のプログラムによって利用されるデータを1つの場所で保管するもの。

###ファイルシステムとデータベースの違い

- ファイルシステム
 - 必要な情報がどこにあるのかをそれぞれプログラムで記述しなければならない。
 - 同時実効性を保つ仕組みがないので、開発者がプログラムで制御する必要がある。
- データベース
 - 必要な情報がどこにあるかはデータベースが管理してくれるのでデータがどこにあるかを意識する必要がない。
 - 同時実効性を保つ仕組みがDBMSで提供される。

##データベースの種類

- データベースには以下の3種類がある。
 - 階層型データベース
 - ネットワーク型データベース
 - リレーショナル型データベース

###階層型データベース
- 会社の組織図のようにデータはツリー構造で表せる。ある一つのデータが複数のデータに対して、親子の関係を持つ。
- データのアクセス方法は一通りしかない。
- 冗長/重複が発生しやすくなる。
- 階層構造に変更があった場合、それに合わせたプログラムの変更が必要になる。

###ネットワーク型データベース
- データは網の目で形で表現され、それぞれのデータ単位（ノード）が繋がっているから、ネットワーク型と呼ばれる。
- 複数の親データへのアクセスが可能。
- 冗長性排除


以上の2つのデータベースはデータ構造への依存性が強いため、構造を意識したプログラミングの必要性や**データ構造変更に伴うプログラム改変の必要性**は、メンテに大きな負荷がかかる。そこで出てきたのが、今回の本題であるリレーショナル型データベース。

###リレーショナル型データベース(以下、RDBMS)
- データを行と列から構成される2次元の表形式で表す。
- データ同士は複数の表と表の関係によって関連つけられ、SQL(構造化問合せ言語)によりユーザーの目的に応じて簡単に操作可能。
- 上記2つのDBと比較して以下のようなアドバンテージがある。
 - プログラムとデータの分離
 - 柔軟化つ容易なデータの取り出し
 - データベース操作の簡略化

RDBMSについてもっと掘り下げてみる。

#RDBMS
##RDBMSの主な構成要素
- 表（テーブル）、データベース・エンジン、SQLの3つで構成されている。
 - 表（テーブル）はデータを格納する。
 - データベース・エンジンはRDBMSに対して操作を行う。
 - SQLはRDBMSに要求を出す言語。

###表（テーブル）
- RDBMSはデータを行（ロー、レコード）と列（フィールド、カラム）の2次元構造で格納する。

###データベース・エンジン
1. RDBMSに対してクライアント側（プログラム実行部分）からリクエスト要求があったとする。
2. クライアントの要求は一旦、「データベース・エンジン」に渡される。
3. データベース・エンジンがクライアントに変わってRDBMSへの処理を行う。
4. その結果をRDBMS→クライアントに返す。

###SQL(Strutured Query Languageの略)
- SQLは以下の3つに分類できる
 - データ定義:データを格納する表を定義。
 - データ操作:表に対してデータの検索、更新、挿入、削除、複数の表を結合。
 - トランザクション機能:データを更新してから、更新情報が確定するまでの一連の流れを管理。

##RDBMSを利用したデータ取り出しの簡単な流れ（おさらい）

1. クライアントからRDMBSに対してSQLを使って、リクエストを要求する。
2. SQLによって要求されたリクエストをデータベース・エンジンが受け取る。
3. SQLの要求に対してデータベース・エンジンがディスク内の表からそれに対応するデータを取り出す。
4. データベース・エンジンが取り出したデータをクライアントに返す。


#感想
簡単ではあるがデータベースとは何か、そしてデータベースがどういう風に使われているのかを理解することができた。下記の参考文献はデータベースに関しての図解があり、入門者の私にも理解しやすかった。

また、データベース・エンジンはruby on railsのMVCモデルのC(controller)のような役割似ていると感じた。
Ruby on Rails チュートリアルかじっていてよかった。


######参考文献

「基礎から始めるデータベース入門セミナー」
https://www.oracle.com/technetwork/jp/articles/index-155234-ja.html
codester チームメンバーの管理, 

https://docs.aws.amazon.com/ja_jp/codestar/latest/userguide/how-to-add-team-member.html
### AWS CodeStar ロールとチームメンバーシップの利点
- チームメンバーの IAM でアクセス許可を手動で設定する必要はありません。

- チームメンバーのプロジェクトへのアクセスレベルを簡単に変更できます。

- ユーザーは、チームメンバーである場合にのみ、AWS CodeStar コンソールでプロジェクトダッシュボードにアクセスできます。

- プロジェクトへのユーザーアクセスは、ロールによって定義されます。

### CodeStar と連携する Managedサービス

- コードはCodeCommit に。Git credentialsは IAM Userに。
SF組織でObjのCRUD権限を時間帯で制限する（Salesforce組織のメタデータを自動バックアップするツール作ってみたその２）

#結論
　前回作成したSFのメタデータ自動バックツールを応用すれば、様々な権限をタイムトリガーで変更できます。

（前回の記事は[こちら](https://qiita.com/bigyoujdb/items/b0331ad0df5511ec6b6a)）

#今回試したもの

前回のものに加えて以下のものを作成しました。

```
myorg
┣mydeploytest
┃ ┗package.xml
┃ ┗profiles
┃ 　┗testCustom.profile
┣ build.xml
```

・testCustome.profile：プロファイルの権限を定義

```testCustome.profile
    **********************
    いろいろ書いてある
    **********************
    
    <objectPermissions>
        <allowCreate>false</allowCreate>
        <allowDelete>false</allowDelete>
        <allowEdit>false</allowEdit>
        <allowRead>false</allowRead>
        <modifyAllRecords>false</modifyAllRecords>
        <object>NotAccessOnEvening__c</object>
        <viewAllRecords>false</viewAllRecords>
    </objectPermissions>

    *********************
    いろいろ書いてある
    *********************
```

・build.xml：Ant で実行されるコマンドを定義。

```build.xml
<?xml version='1.0' encoding='UTF-8'?>
<project xmlns:sf="antlib:com.salesforce" name="Sample usage of Salesforce Ant tasks" default="test" basedir=".">

    <property file="build.properties" />
    <property environment="env" />

    
    <condition property="sf.username" value=""> <not> <isset property="sf.username" /> </not> </condition>
    <condition property="sf.password" value=""> <not> <isset property="sf.password" /> </not> </condition>
    <condition property="sf.sessionId" value=""> <not> <isset property="sf.sessionId" /> </not> </condition>

    <taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce">
        <classpath>
            <pathelement location="../ant-salesforce.jar" />        	
        </classpath>
    </taskdef>

    <target name="deployUnpackaged">
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="mydeploytest" rollbackOnError="true" />
    </target>

    
</project>
```

　以上を用意して、'Ant deployUnpackaged'を実行すれば、testCustome.profileで定義されている通りに、SF組織のプロファイルが変更されます。
testCostomプロファイルの夜間アクセスできないオブジェクト（NotAccessOnEvening__c）に対する全ての権限がfalseに変更されます。

#使いどころ
　例えば、「取引先オブジェクトには24時間アクセスできるようにしておいてほしいが、あるカスタムオブジェクトには0時00分から8時00分の夜間に参照も出来ないようにして欲しい」みたいな要件があったら、こんな方法でも実装できるかなと思いました。
(まあ、夜間のみ'参照'もさせたくないっていう要件はなかなかないだろうし、'編集'させないで欲しいという要件なら入力規則で満たせますが...)

#今回ちょっとはまったポイント
　プロファイルのメタデータを組織から取得する際に、あるオブジェクトに対して、'表示'権限までない場合、'.profile'ファイルの中身には、カスタムオブジェクトのアクセス権に関する定義が書いていませんでした。プロファイルの＜objectPermissions＞ブロックの記載を組織から取得したい場合は、最低でも一つのカスタムオブジェクトに対して、'表示'がTrueになっていないといけないみたいです。

#まとめ
　今回のツールは、「実際にユーザのSF運用で使用するか」でいうと使用することはほぼありえないでしょうが、こんなことも出来て面白いという記事でした。「要件を満たす成果物が出来たら終了」ではなく、「それを使ってあんあこと、こんなことも出来ないかな」というマインドは常に持ち続けていきたいと思います。
tableau serverのデータソース自動更新　

# やりたいこと
TableauServerにpublishしたデータを自動で更新したい

## 前提条件
* 大本のデータソースはDBまたはCSV。これをPrepにてデータ処理して出力したhyperがデータソースとしたい
* PrepからTableauServerにpublishするとPrepがよくこけるので別手段を検討
* Prepのデータ処理は定期的に実行されれる。
* tableau2020.1


# 方法案と結果

|ルート|期待|判定|方法|結果|
|---|---|---|---|------|
|1|◎|×|NASのhyper形式をtableauserverで自動更新|NASのhyperにtableauserverからアクセスできない|
|2|〇|△|Prepで更新|データが大きいためかPrepが落ちることがよくある|
|3|〇|〇|tableauserverでtabcmd publishを行う|更新できた|
|4|△|×|tableau refreshextract を使う|更新できなく、何もメッセージがでないので原因不明|
|5|△|×|GoogleDrive上のhyper|そもそもGoogleDrive上のhyperはtableauに読み込めない|
|6|×|△|GoogleDrive上のエクセル|更新できた。しかし、hyper形式が望ましい|
|7|×|△|tableauで手動更新|できるが、手動更新はつらい|



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573747/2de6b1f1-6a84-3e3f-8607-16f0596e77a3.png)




# tabcmdでデータ更新
結局、この方法がよさそう。

```
tabcmd publish "ファイル名.hyper(ファイルサーバでもOK)" -r "プロジェクト名" -n "データソース名" -u "tableauserverユーザ名" -p "tableauserverパスワード" --server "サーバ名（http://は不要）" -o
```
補足
-o:上書き


[tabcmd](https://help.tableau.com/current/server/ja-jp/tabcmd_cmd.htm)
sshd&sshのハマりやすいポイント

# この記事について
久しぶりに新しいサーバに公開鍵を置いてSSH認証できるようにしようと思ったらハマったのでメモ。

# 環境
サーバ側: Red Hat Enterprise Linux 7.4
クライアント側: CentOS 7.4

# ハマりやすいポイント(気をつけるポイント)
## サーバ側(ログインされる側; リモート側)
### `authorized_keys` のファイル名
デフォルト値では `authorized_keys` 以外使えない。
たとえば、`Authorized_keys` とか `authorizedkeys` とかのファイルは認識されない。
詳しくは、 `sshd_config(5)` を参照。

### `$HOME/.ssh` ディレクトリ
`$HOME/.ssh` ディレクトリのパーミッションを `700` にしておく必要がある。

## クライアント側(ログインする側; ローカル側)
### `$HOME/.ssh` ディレクトリ
サーバ側と同じで `$HOME/.ssh` ディレクトリのパーミッションを `700` にしておく必要がある。

### 秘密鍵のファイル名
デフォルトでは下記のファイルが秘密鍵として使われる。

- `$HOME/.ssh/id_dsa`
- `$HOME/.ssh/id_rsa`
- `$HOME/.ssh/id_ecdsa`
- `$HOME/.ssh/ed25519_rsa`

詳しくは `ssh_config(5)` を参照。

### `config` のパーミッション
クライアント側にある `$HOME/.ssh/config` ファイルも、パーミッション `600` である必要がある。
(`$HOME/.ssh` が `700` であるだけでは不可)
データサイエンティストのトレーニング on R ~webサービスを自分で作る医者の日記~

今日は、決定木について

サンプルコード

```
set.seed(9999)
DF <- read.table("hoge", 
                 sep=",", 
                 header = T, 
                 stringsAsFactors = F, 
                 fileEncoding = "UTF-8")
head(DF)
str(DF)
summary(DF)
library(rpart)
CRT1 <- rpart(契約 ~ ., 
                data=DF[ ,-1], 
                method="class")
CRT1
library(rpart.plot)
rpart.plot(CRT1, tweak=1.0, roundint=F)
par(family = "HiraKakuProN-W3")
rpart.plot(CRT1, 
           type=4, 
           extra=1, 
           under=T, 
           roundint=F)
prp(CRT1, 
    type=4, 
    extra=101, 
    nn = T, 
    tweak=1.0, 
    space=0.1, 
    shadow.col = "grey", 
    col="black", 
    split.col="brown3", 
    branch.col="brown3", 
    fallen.leaves=F, 
    roundint = F, 
    box.col=c("pink", "palegreen3")[CRT1$frame$yval])
CRT2 <- rpart(契約 ~ ., 
                data=DF[ ,-1], 
                method="class", 
                control=rpart.control(minsplit=20, 
                                      minbucket = 10, 
                                      maxdepth = 20, 
                                      cp=0.005))
```
Markdown メモ

|やりたいこと|書き方||やりたいこと|書き方|
|:--|:--|:-:|:--|:--|
|タイトル | \#タイトル  ||・| \-項目 
|リンク | \[リンク名](http:) ||エスケープ| \|
|番号 | 1. aa<br>1. bb ||コード| \`\`\`<br>aaa<br>``` 
|横棒 | ---   ||太字| \*\*\*aaa***
|赤文字 | <font color="Red">あ</font>||インライン| \`\`\`aaa```
|折りたたみ | <details><summary>折りたたみ</summary><div>あああ</div></details>||| 

---
- VSCode

|矩形選択|書き方|
|:--|:--|
|Win|［Ctrl］＋［Shift］＋［Alt］＋矢印キー|
|Mac|［Shift］＋［Option］＋［Command］＋矢印キー|

参考URL
* [Qiita マークダウン記法 一覧表・チートシート](https://qiita.com/kamorits/items/6f342da395ad57468ae3)
Jenkins Scripted Pipeline で他のジョブをビルドする

特に説明することもないのでコードだけ。

```groovy:Jenkinsfile
node {
	properties([
		parameters([
			string(name: 'MESSAGE', description: 'メッセージ'),
		])
	])
	stage('build') {
		build job: 'build', parameters: [
			[ $class: 'StringParameterValue', name: 'MESSAGE', value: "${params.MESSAGE}" ],
		]
	}
}
```
簡単なForm作成から学ぶVue(TypeScript)の書き方 その0 環境構築編

Dockerを用いてVue環境を作り、いい感じのフォームを作成しながらVueを学習していく。

# Dockerざっくりした理解

## Dockerコンテナ

→ アプリケーションの実行環境
ホストOS上に論理的な区画を作ったもの。OSやIPアドレスなどのシステムリソースをコンテナが見かけ上占有できる。
コンテナに必要なモジュールのみを詰めてアプリケーションを実行できる。

## Dockerイメージ

→ コンテナを構成するための設計図。
DockerHubを介して種々のイメージを共有できる。

## Dockerコマンドの利用

よくあるDockerの練習としてnginxを用いたサーバー構築がある。

```shell:nginxでサーバー構築
$ docker pull nginx 　　　　　　　　　　　　　　　　　//DockerHubからイメージ取得
$ docker run --name webserver -d -p 80:80 nginx //起動。デーモン化。ブラウザからアクセスできるようになる。
$ docker ps 　　　　　　　　　　　　　　　　　　　　　 //プロセス確認
$ docker stop webserver 　　　　　　　　　　　　　　 //停止
$ docker rm webserver　　　　　　　　　　　　　　    //削除
```

## Dockerfile

→ DockerfileはDockerイメージを構成するための構成情報ファイル。
上の練習ではDockerHub上のイメージを取得し、そのまま起動させるものだが、実際の開発では、内部の構成に手を加え、独自のイメージを創り、コンテナを生成することとなる。
コマンドで環境を構築してもよいが、本格的な開発となった場合に以下のような構成情報を別途ドキュメントとして残す必要が出てしまう。

* 元となるDockerイメージ
* コンテナ内で実行するコマンド
* 環境変数などの設定値

こうした構成情報を記述しておくファイルがDockerファイルであり、`docker build`コマンドを用いると、このDockerfileを元にしてDockerイメージを作成できるため無駄やミスがない。

## Docker Compose

これまでのDockerは1つのコンテナを用いる話だった。先述の通りコンテナは論理的に１区画を創るものであり、複数のコンテナを生成することもできる。複数のコンテナを生成し、それらをコンテナ内部のネットワークで繋ぐこともできる。

これらを束ねるのがdocker-composeであり、その設定ファイルがdocker-compose.ymlである。

# vue環境の構築

参考→https://cloudpack.media/43078

正直この通りやっていけばできる。複数選択のものはスペースで選択できる。
設定は少し変更あり。

```:Dockerfile
FROM node:10.8.0-stretch
 
RUN npm install --global @vue/cli
 
WORKDIR /projects
```

```:docker-compose.yml
version: '3'
 
services:
  app:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - ".:/projects"
    tty: true
```

```shell
$ docker-compose up -d
$ docker-compose exec app bash
```

```:設定部分
# vue create app

Vue CLI v4.0.5
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, PWA, Router, Vuex, CSS Pre-processors, Linter, Unit, E2E
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-sass)
? Pick a linter / formatter config: Basic（一番目を選択）
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lint on save
? Pick a unit testing solution: Mocha
? Pick a E2E testing solution: Cypress
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
? Pick the package manager to use when installing dependencies: NPM
```

構築が終わったらappディレクトリに移行して下のコマンドを実行。ブラウザから`localhost：8080`にアクセスして確認。

```
 # cd app
 # npm run serve
```

ctrl+Cで終了し、`exit`でDockerから抜けた後`$ docker-compose down`でコンテナごと終了。

# お世話になった参考サイト

* https://cloudpack.media/43078
* https://tech-up.hatenablog.com/entry/2019/03/15/152258
Qiitaってプログラマーのブログと聞いてアカウントを作成しました

#５０の手習いでプログラミングを学びはじめる

Pythonをストアカの講座で学びました。その時に先生から（すごい若くてカッコいい）Qiitaはプログラマーのブログだと聞いてアカウントを開設してみました。

ついでにGitHubも開設、プログラム学習の備忘録にしようと思います。

#QiitaってMarkdown記法なの？
すこし慣れないと難しいかも。。。見出ししかわからないｗ

#ストアカでの備忘録
- Pythonのインストール
- Anacondaのインストール
  - ターミナルを使った動作
- Webページの見出しのスクレイピング
 - テーブルタグのスクレイピングソース
- brewを使ったSeleniumｍのインストール
 - サイトのログインやページ操作
 - ページの情報収集
 - XPATHの使い方

備忘録といいつつ半分以上忘れている感じがあり
やばいです、、、ジュピター含めて明日から復習していきます。
Use Cases for DAX

## 参考
https://docs.amazonaws.cn/en_us/amazondynamodb/latest/developerguide/DAX.html#DAX.use-cases

### Use Cases for DAX
- DAXは、マイクロ秒のレイテンシで、DynamoDBテーブルから最終的に一貫したデータへのアクセスを提供します。 Multi-AZ DAXクラスターは、1秒あたり何百万ものリクエストに対応できます。

- DAXは、次の種類のアプリケーションに最適です。
  - 読み取りに可能な限り速い応答時間を必要とするアプリケーション。一部の例には、リアルタイム入札、ソーシャルゲーム、取引アプリケーションが含まれます。
  - 少数のアイテムを他のアイテムよりも頻繁に読み取るアプリケーション。たとえば、人気のある商品の1日販売があるeコマースシステム

- **読み取り集中型であるが、コストに敏感なアプリケーション。**
   - DynamoDBでは、アプリケーションが必要とする1秒あたりの読み取り数をプロビジョニングします。読み取りアクティビティが増加した場合、テーブルのプロビジョニングされた読み取りスループットを増やすことができます（追加費用がかかります）。または、アクティビティをアプリケーションからDAXクラスターにオフロードし、別の方法で購入する必要がある読み取りキャパシティーユニットの数を減らすことができます。

- **大量のデータに対して繰り返し読み取りが必要なアプリケーション。**
  - このようなアプリケーションは、データベースリソースを他のアプリケーションから迂回させる可能性があります。たとえば、地域の気象データの長期にわたる分析では、DynamoDBテーブルのすべての読み取り容量が一時的に消費される可能性があります。この状況は、同じデータにアクセスする必要がある他のアプリケーションに悪影響を及ぼします。 DAXを使用すると、代わりにキャッシュされたデータに対して気象分析を実行できます。

- DAXは、次の種類のアプリケーションには理想的ではありません。
  - 強く一貫した読み取りを必要とする（または最終的に一貫した読み取りを許容できない）アプリケーション。
  - 読み取りにマイクロ秒の応答時間を必要としないアプリケーション、または基になるテーブルから繰り返し読み取りアクティビティをオフロードする必要のないアプリケーション。
  - 書き込み集中型のアプリケーション、または読み取りアクティビティをあまり実行しないアプリケーション。
  - DynamoDBで別のキャッシングソリューションを既に使用しており、そのキャッシングソリューションを操作するために独自のクライアント側ロジックを使用しているアプリケーション。
テンプレートの検証

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-validate-template.html

テンプレートファイルの構文エラーを確認するには、aws cloudformation validate-templateコマンドを使用できます。

- 使い時
  - syntaxチェック
  - rollback したときに同じ状態になっているか確かめる
ESP32でLチカをする。

##目標
ESP32の開発に必要なArduino IDE 側の設定をし、ESP32で内蔵のLEDを点滅させる。

##環境
- macOS 10.15.2 Catalina
- Arduino IDE 1.8.10
- ESP32 DEVKIT V1 (ESP-WROOM-32)
- LED
- 抵抗 100[Ω]

##プログラム
###Arduino IDE の設定
下の記事を参考に設定する。
>https://entotsu44.hatenablog.com/entry/2019/12/23/171713
数値の表現を学んだことについて

数値の表現方法を色々と勉強したので適当にまとめてみます。

いきなりですが、符号化とは
*ある情報の集合の各要素に対して、nビットの符号を対応付けることである*

また、ある数値Xをnビット

```math
x_{n-1}x_{n-2}...x_{2}x_{1}x_{0}
```

で表すと、r進法では

```math
X=\sum_{i=0}^{n-1}x_{i}r^i
```

と表現できます。この時の最小値Xminと最大値Xmaxを表現すると

```math
Xmin = 0\\
Xmax = 2^n-1
```
Xminはxiが全て0なので上記の結果になり、Xmaxはxiが全て1なので

```math
Xmax=\sum_{i=0}^{n-1}r^i
```
この式が成り立ち、これは交差rの数列なので数列の和の公式により

```math
Xmax=\frac{初項(1-r^{n})}{1-r}
```
上記の式で求まります。

これまでは符号なし数の説明でした。
次は、符号あり数の説明です。符号ありには、絶対値表現・1の補数表示・2の補数表示の3種類あります。

#符号付き数
ここでは、nビットあるXを1ビットのSとn-1ビットのX*で表すことにします。
Sは最左ビットで符号ビットとして扱います。
S=0なら正で、S=1なら負です。
X*の範囲はこうです。

```math
0\leqq X^*\leqq2^{n-1}-1
```

##符号-絶対値表現

```math
X=(-1)^SX^*
```
<br>

```math
\begin{align}
Xmax &=(-1)^0*X^*max\\
&=2^{n-1}-1
\end{align}
```
<br>

```math
\begin{align}
Xmin &=(-1)^1*X^*max\\
&=-(2^{n-1}-1)
\end{align}
```
<br>

```math
-(2^{n-1}-1)\leqq X^*\leqq2^{n-1}-1
```


##1の補数表示

```math
X=(-2^{n-1}+1)S+X^*
```
<br>

```math
\begin{align}
Xmax &=(-2^{n-1}+1)^0+X^*max\\
&=2^{n-1}-1
\end{align}
```
<br>

```math
\begin{align}
Xmin &=(-2^{n-1}+1)^1+X^*min\\
&=-(2^{n-1}-1)
\end{align}
```
<br>

```math
-(2^{n-1}-1)\leqq X^*\leqq2^{n-1}-1
```


##2の補数表示

```math
X=(-2^{n-1})S+X^*
```
<br>

```math
\begin{align}
Xmax &=(-2^{n-1})^0+X^*max\\
&=2^{n-1}-1
\end{align}
```
<br>

```math
\begin{align}
Xmin &=(-2^{n-1})^1+X^*min\\
&=-2^{n-1}
\end{align}
```
<br>

```math
-2^{n-1}\leqq X^*\leqq2^{n-1}-1
```

##例として分かりやすい表を作ってみた

|10進数|符号なし|絶対値表現|1の補数|2の補数|
|:----:|:-----:|:------:|:----:|:----:|
|+4|0100|0100|0100|0100|
|+3|0011|0011|0011|0011|
|+2|0010|0010|0010|0010|
|+1|0001|0001|0001|0001|
|+0|0000|0000|0000|0000|
|-0|-|1000|1111|-|
|-1|-|1001|1110|1111|
|-2|-|1010|1101|1110|
|-3|-|1011|1100|1101|
|-4|-|1100|1011|1100|

ここから分かるように、

 - 符号なしでは負の数は表せられない
 - 絶対値表現で負の数を表すときは、最左ビットを反転させている
 - 1の補数で負の数を表すときは、全ビットを反転させている
 - 2の補数で負の数を表すときは、全ビットを反転させて1を加えている
 - 2の補数では-0がない。また、絶対値表現と1の補数では0の+-でダブりがある

#まとめ
分かりやすいかは置いといて、簡単にまとめました。
数値の表現といっても色々な表現方法があることが分かりました。
この表示方法によって、桁落ちとか情報落ちとかが出てくるのかな？
独自のモディファイアを作成する

## SwiftUIのモディファイアを独自で設定することができる
- 複数のビューに同じ加工をしたい場合や、共通的に処理を作成したい場合はモディファイアが有効です。

## サンプル

- モディファイア

```swift

struct SampleModifier: ViewModifier {
    func body(content: Content) -> some View {
        return content
            .font(.title)
            .padding(.horizontal, 10.0)
            .background(Color.red)
            .cornerRadius(3.0)
    }
}

extension View {
    func samplemodifier() -> some View {
        self.modifier(SampleModifier())
    }
}

```

- 適用するView

```swift

Text("ありがとう")
    .samplemodifier()

```
Pythonista3を使ってTwitterのTLをiphoneに音読してもらう

# 背景
仕事が終わってTwitterのTLを見ようかと思っても、他にやりたいことが多くてTwitterを見る時間がとれないので、iPhoneが話してくれるのを聞くだけで済むようにした。

# 環境
iPhone8 13.2.3
Pythonista3 3.2
Tweepy 3.5.0

#準備
・Pythonista3のインストール
・Twitter APIの登録申請
(参考:[PythonでTwitter API を利用していろいろ遊んでみる](https://qiita.com/bakira/items/00743d10ec42993f85eb))
・StaShのインストール
(参考:[Pythonista 3 にStaSh をインストールする。](https://qiita.com/maboy/items/cef5dee13d5b2e9ac843))
・Tweepyのインストール

#ファイル構成
今回私は以下のようなファイル構成にした。
├─twitterconfig.py   #認証情報を管理
├─sp_timeline.py    #実際に動かすコード
└

#コード
```sp_timeline.py
#!Pythonista3
#自分のTLをiphoneに読んでもらうプログラム

import time, speech, twitterconfig
from twitterconfig import api

shu_kai = 0
maxid = None
while True:
	home_tweet = api.home_timeline(max_id=maxid)
	#2周目で1周目の最後と2周目の初めのツイートが重ならないようにする処置
	if maxid != None:
		home_tweet = home_tweet[1:]
	for tweet in home_tweet:
		print('__________________________________________')
		#ツイート主の表示
		print(tweet.user.name + '(@' + tweet.user.screen_name +')')
		#ツイート文の表示
		print(tweet.text)
		#リンクは音読させない
		if 'https' in tweet.text:
			https_ofset = tweet.text.find('https')
			tweet.text = tweet.text[:https_ofset]
		speech.say(tweet.text, 'ja-JP', 0.5)
		time.sleep(15)
	shu_kai += 1
	shu_kai_text = str(shu_kai) + '周目終了'
	print('--------------',shu_kai_text,'--------------')
	#maxidを最後のtweet.idにして、次はこれより古いtimelineを持ってくるようにする。
	maxid = tweet.id
	time.sleep(60)
```

#結果
他に作業しながらTLを聞くことができるので、私のようなTwitter依存者には何かの役に立つかもしれません。
けれど、iPhoneさんの発音があまりよろしくないので、他に誰か探してみるとよいかも・・・
作業３日目②　イラストの回転　InspectorのRotation

ボタンを作る作業をするはずが
手っ取り早く
何か１つを成し遂げたくなったゆっきー。


２週間前から
ゆっきーは
回転の仕方がわからなかった。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/9b1ef6b2-8117-2112-8551-1b58229ee24e.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/306be6a9-aac7-2a42-5d41-e7df0d74bf9a.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/0d080ebc-a3e7-bd3c-11c2-754c49d7be86.png)



Zを変えれば良かったんだ～～～！！！

Yだと思ってた～～～～！！！



はい。
ゆっきーはそんなレベルです。

でも、今日かなりうれしいかもしれない。←真剣にわからなかった。（３週間以上かかった）。


１つクリア！！
Tkinterで画面切り替え・画面遷移

#Tkinterで画面切り替え
超シンプルなコード紹介。
別記事( [ここ](https://qiita.com/seisantaro/items/3801886a6b0a500c4933) )はOpenCV関係のコードで長くなっちゃったんでこっちは短くまとめる。
pillowが入ってれば動くはず。
##コード
```python:main.py
# -*- coding: utf-8 -*-
import tkinter as tk
import PIL.Image, PIL.ImageTk

class App(tk.Tk):
    # 呪文
    def __init__(self, *args, **kwargs):
        # 呪文
        tk.Tk.__init__(self, *args, **kwargs)

        # ウィンドウタイトルを決定
        self.title("Tkinter change page")

        # ウィンドウの大きさを決定
        self.geometry("800x600")

        # ウィンドウのグリッドを 1x1 にする
        # この処理をコメントアウトすると配置がズレる
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
#-----------------------------------main_frame-----------------------------
        # メインページフレーム作成
        self.main_frame = tk.Frame()
        self.main_frame.grid(row=0, column=0, sticky="nsew")
        # タイトルラベル作成
        self.titleLabel = tk.Label(self.main_frame, text="Main Page", font=('Helvetica', '35'))
        self.titleLabel.pack(anchor='center', expand=True)
        # フレーム1に移動するボタン
        self.changePageButton = tk.Button(self.main_frame, text="Go to frame1", command=lambda : self.changePage(self.frame1))
        self.changePageButton.pack()
#--------------------------------------------------------------------------
#-----------------------------------frame1---------------------------------
        # 移動先フレーム作成
        self.frame1 = tk.Frame()
        self.frame1.grid(row=0, column=0, sticky="nsew")
        # タイトルラベル作成
        self.titleLabel = tk.Label(self.frame1, text="Frame 1", font=('Helvetica', '35'))
        self.titleLabel.pack(anchor='center', expand=True)
        # フレーム1からmainフレームに戻るボタン
        self.back_button = tk.Button(self.frame1, text="Back", command=lambda : self.changePage(self.main_frame))
        self.back_button.pack()
#--------------------------------------------------------------------------

        #main_frameを一番上に表示
        self.main_frame.tkraise()

    def changePage(self, page):
        '''
        画面遷移用の関数
        '''
        page.tkraise()

if __name__ == "__main__":
    app = App()
    app.mainloop()
```
##ざっと解説
ポイントはtkraiseというコマンド。tkraiseは指定のフレームを最前面に表示させる。
フレームを重ねて配置して、ボタンを押すたびに裏にあるフレームを持ってくる構成。
ボタンにはなんの装飾もせず超シンプルにしてあります。
##図解
こんなイメージ
![コメント 2020-01-26 202500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533911/a9648a42-6613-9bf2-516d-863986c5a144.png)
##詳しく説明
コード中のコメントアウトに大体のことは書いてあるけど一応、、

まずメインフレーム(main_frame)と移動先のフレーム(frame1)を作成。
2つのフレームをgridメソッドを使って座標(0,0)に配置
gridを使うことで重ねて配置することが出来る。
タイトルラベルについては特に言うことなし。
ボタンウィジェットはcommandにchangePage関数を指定する。
changePage関数は引数にフレーム名をとる。
因みにボタンウィジェットのcommandに引数(selfはカウントしない)をとる関数を指定する場合、
`command=lambda :関数`
とする必要がある。
##おわり
かなり短いコードにしたので分かりやすいと思う。
今まで僕が見た中で最短だもの。
もちろんtkraiseを使わずその都度ページを表示したり消したりするやり方もあるけど一番簡単なのはtkraiseだと思う。
pybullet installメモ

0.環境
・Windows10
・anaconda3.7

1.PATHの設定
後のためにPAHを通しておくと、pipだけで起動できる。(pythonを実行してpipでも可能と思われるが)
PATHはコマンドプロンプトから下記のようにして確認できる。

C:\Users\**>where python
C:\Users\**\Anaconda3\python.exe
C:\Users\**\AppData\Local\Microsoft\WindowsApps\python.exe

2.インストール
2-1.Visual Studio c++が入っている場合
以下のとおり、pip installでインストール可能。

C:\Users\**>pip install pybullet
Collecting pybullet
  Using cached https://files.pythonhosted.org/packages/25/98/9478dce17f53b8129165d0ee1f569a628340cf2d337ddb7b35d5014490b1/pybullet-2.6.4.tar.gz
Requirement already satisfied: numpy in c:\users\nori\anaconda3\lib\site-packages (from pybullet) (1.16.5)
Building wheels for collected packages: pybullet
  Building wheel for pybullet (setup.py) ... done
  Created wheel for pybullet: filename=pybullet-2.6.4-cp37-cp37m-win_amd64.whl size=72376304 sha256=144663282be94c1ed770335125cc17a61a26a82cfe7bab06108e70d8bdad037f
  Stored in directory: C:\Users\**\AppData\Local\pip\Cache\wheels\93\91\e5\ab781518019d07e6bbbd0fadf55ddf270bb971430b669bfa55
Successfully built pybullet
Installing collected packages: pybullet
Successfully installed pybullet-2.6.4

2-2.Visual Studio c++が入っていない場合
上記を実行すると、Visual C++ 14.0 が必要というエラーが出る。
Build Tools for Visual Studio 2019をダウンロードしてきて、V14をインストールすること。
※Build Tools for Visual Studioを起動してエラーが出たので、(念のため)Visual Studio Codeも入れてからインストール実行したら、Build Toolもインストールできた。Visual Studio Codeが必要なのかは不明だが。
作業３日


　ゆっきーの作業３日目　　




今日のやりたいこと。
・ボタンを追加したい。
　　　　↓
・ので今日は先生が作ってくれたプログラミングを読み解く努力をする。





● [SerializeField]

・インスペクターウィンドウで編集できるようにすること

・publicより定義を変えにくいので
　複数の人が関わる分業の時に適している

（つまり、publicの場合はフィールドの定義を変えやすいので
　誰かが知らずに一人で定義を変更すると、動かなくなってしまう場合がある）






![small_girl_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/a8e1214e-a25f-753b-0a3d-3a63141159fa.png)　（ほう）






● Transform

Transformは、オブジェクトの「位置」「回転」「縮尺」を設定するコンポーネント。
大きさや配置場所が決まる。




![small_girl_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/a8e1214e-a25f-753b-0a3d-3a63141159fa.png)　（これ、Unityアセットもこれで変更できるのかな・・・）




●List

Listは配列ととても良く似たものです。
配列を宣言するときは、初めから配列の個数は決められています。
しかし、Listの場合は長さを決めずに宣言することができます。その時によって要素数を増減させることができます。



![small_girl_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/a8e1214e-a25f-753b-0a3d-3a63141159fa.png)　（配列って何？・・・とりあずわからないけど次！）


●リストの定義方法はこれらしい。
private List<int> myList = new List<int>();




![small_girl_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/a8e1214e-a25f-753b-0a3d-3a63141159fa.png)　（intって・・・？）



●int

int a;
と宣言し
a=10;
となると

int型の変数aに値１０を入れる




・・・

・・・


![cairo_girl_yoko.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/91069496-e068-17b7-1917-7e1c41df2fd3.png)
（ゲームオーバー。ライフ１つ失う。）



というか
ボタンを作るつもりが別なスクリプトを見ていたこと事にきづいた為
一旦終了。

ボロボロ過ぎやな。

あまり私を信じずブログをお読み下さい。


次に続く。
SQL　テーブルの結合

テーブルの正規化
テーブルを分けて情報の重複をなくす

メリット
データ管理が容易になる
データ容量の削減

主キー
1つの行を特定できる列のこと

外部キー
他のテーブルとの関連付けに使う列のこと
外部キーは関連付けされたテーブルでは主キーとなる

関係性
一対多
多対多
一対一

内部結合
select テーブル名.カラム名 from テーブル名 
inner join 結合するテーブル名 
on テーブル名.カラム名 = 結合するテーブル名.カラム名;

記述順序
select from 結合処理 where group by having order by limit
実行順序
from 結合処理 where group by having select order by limit
作業１日目,２日目


作業１日目と２日目は
Qittaのブログ開設も失敗し・・・

自分のWebsiteに記載。

※１つのTwitterでメール認証失敗した為、新しくユーザー登録しようとしたら
古いのQittaブログと新しいQiitaブログで混乱して開設できなかった(=_=)。ﾏｻｶブログも開設ﾃﾞｷﾅｲﾅﾝﾃ・・・。


忘備録として下記リンクに記載しときます。
https://yukiplan.jp/%e4%bc%9a%e7%a4%be%e6%a6%82%e8%a6%81/


![small_girl_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/057c4da8-4cc3-cbb4-b576-eba2fe191f2a.png)
BufferedReaderの使い方について


##はじめに
BufefedReaderの使い方について説明します。
使用後は、AtCoderの問題で処理速度が改善しました。

##BufferdReaderの使い方
実装内容です。BufferedReaderクラスの中身は [リンク](https://qiita.com/kazu00/items/6b07a335fda77127480c)先の方が書いておりましたのでご参考まで。（大変参考になりました）

```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
　　　　　　　　　〜省略〜

BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
int stay = Integer.parseInt(input.readLine());
　　　　　　　　　〜省略〜
```

`BufferedReader`クラスのインスタンス化はお決まりの記載なので、暗記で大丈夫です。

注意点はメソッドのreadLineメソッドが入力を一行ずつ取得する点ですね。一行でスペース区切りで配列に分けたい場合は`split`メソッドを使用するのが良いかと思います。

またお恥ずかしい話ですが、例外処理も詳しく把握していなかったのでこちらの[サイト](http://www.media.osaka-cu.ac.jp/~matsuura/2008-PP/Exception.html
)を参考にしました。


##今までは何を使っていた？
今までは`Scanner`クラスをつかっていました。以下の通り実装してました。

```
import java.util.Scanner;
        　　　　〜省略〜
Scanner sc = new Scanner(System.in);
String s = sc.next();

　　　　　　　　　〜省略〜
```

##実際に変更してみて結果どうなった？

<img width="559" alt="スクリーンショット 2020-01-26 20.33.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429081/da19f60d-3435-3d7b-92c7-63916d93c485.png">


１行目が`BufferedReader`クラス使用後になります。約20％の速度が改善しました。

今回は入力する個数が４つなのでそこまで速度に影響しませんでしたが、今後大量データを処理する問題に直面した際には`BufferedReader`クラスは必須になるのかなと思いました。
Atcoder Beginner Contest 146参戦日記

## C

範囲より全探索が難しいことがわかる。何らかの法則性があると考えてごにょごにょしたが、解けなかった。

この問題のポイントは、
1. $A×N+B×d(N)$円が線型性を持つことに気づくこと
2. 二分探索が線形問題を解決できることに気づくこと
である。

1. は自明。
2. は昇順ソートされた配列は線形関数と同義であることを意識しなければいけない

私は、2.について理解していなかった。

```
A , B , X = map(int,input().split())
ans = 10**9 // 2
diff = ans
digit_ans = len(str(ans))
while not A * ans + B * digit_ans <= X < A * (ans+1) + B * len(str(ans+1)):
    diff = max(diff // 2 , 1)
    if A * ans + B * digit_ans > X:
        ans -= diff
    else:
        ans += diff
    digit_ans = len(str(ans))
    #print(ans)
    if ans >= 10 ** 9:
        print(10**9)
        exit()
    elif ans <= 0:
        print("0")
        exit()
print(ans)

```

## D
ルートを一つ定め、使った色以外を色付けすることで解ける。貪欲法。
配色、探索済みを二次元リストで行おうとしたところTLE。
辞書型を使うことで解決した為、メモリの問題？だと考えられる。
(中盤の大きなコメントアウトは二次元リスト仕様の残党）

```
from collections import deque
# 入力、初期化
N = int(input())
tree = [[] for _ in range(N)]
input_list = []
for _ in range(N - 1):
    a, b = map(int, input().split())
    a, b = a - 1, b - 1
    input_list.append([a, b])
    tree[a].append(b)
    tree[b].append(a)
 
 
# visitedにノードの色を格納する
# visited_edge = [[0] * N for _ in range(N)]
dict = {}
'''
# bfsによる色付けを行う
def bfs(now_node, max_val=0):
    queue = deque([[tree[now_node], -1, now_node]])
    while queue:
        next_nodes, before_color, now_node = queue.pop()
        now_color = 1
        for next_node in next_nodes:
            if visited_edge[now_node][next_node] != 0:
                continue
            if now_color == before_color:
                now_color += 1
            if max_val < now_color:
                max_val = now_color
            visited_edge[next_node][now_node] = now_color
            visited_edge[now_node][next_node] = now_color
            queue.appendleft([tree[next_node], now_color, next_node])
            now_color += 1
    return max_val
'''
def bfs(now_node, max_val=0):
    queue = deque([[tree[now_node], -1, now_node]])
    while queue:
        next_nodes, before_color, now_node = queue.pop()
        now_color = 1
        for next_node in next_nodes:
            key = tuple(sorted([now_node, next_node]))
            if not dict.get(key) is None:
                continue
            if now_color == before_color:
                now_color += 1
            if max_val < now_color:
                max_val = now_color
            dict[key] = now_color
            # visited_edge[now_node][next_node] = now_color
            queue.appendleft([tree[next_node], now_color, next_node])
            now_color += 1
    return max_val
 
ans = bfs(0)
print(ans)
for a, b in input_list:
    # print(visited_edge[a][b])
    print(dict[tuple(sorted([a,b]))])
```
プロローグ（このブログの説明）


ゆっきーです。

これはGooglePlayにはリリースしたけど
Appleの審査に落とされてIphoneリリースの修正を余儀なくされてるゆっきーのブログです。

また、ゆっきーは初心者の為
このブログを忘備録として気まぐれに記録していく事にしました。

また、勝手に他の方の文章をお借りして
ゆっきーがゲーム作成を覚える為の覚書であり、

他の人にまで、がんばりを見せびらかす為の自己満足のブログです。

※引用させていただいた方、すみません。おかげでゆっきーは助かっています。

気長にお付き合いください☆



![small_girl_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569569/d8815f26-5ec5-1c3f-88ae-be8d8898d371.png)
Unity入門 02 はじめてのアプリ

# やったこと
Unityの教科書 Unity2019完全対応版 2D&3Dスマートフォンゲーム入門講座の3章。
はじめてのアプリ作成。
2章はC#の単元だったため割愛した。

# プロジェクト作成
プロジェクトの立ち上げはUnity HubからでもUnity 2018.4.15f1 (64-bit)でもできる

# スクリプトの種類
- コントローラスクリプト
- ジェネレータスクリプト
- 監督スクリプト

ただしこれらは本書特有の呼び方？

# 画像の使い方
- Assetsにドラッグアンドドロップ > AssetsからSceneにドラッグアンドドロップ

これがすごい便利だと感じた。Assetsすごい。

# 先にビルドを決めてしまう
- このとき画面サイズも決めてしまう。

# オブジェクトの位置調整
- 移動ツール or インスペクター

# C#スクリプトの作成
- Assets上で右クリック > Create > C# Script

C#そのものは紐付けたVisual Studio上で編集できる。

# C#スクリプトの紐付け
- AssetsのC#スクリプトをHierarchy上のオブジェクト（紐付けたいオブジェクト）にドラッグアンドドロップ

以降は変更があっても紐付けは解除されないので、紐付けをやり直したりする必要はなし。


# スマートフォン書き出し（Android）準備
UnitySetup-Android-Support-for-Editor-2018.4.15f1.exe
初回にビルドできない旨のメッセージが表示され、上記をダウンロードした。
ダウロード完了後、一度Unityを終了してインストール。
その後、再度Unity HubからUnityを立ち上げた。

- デベロッパモードにしたスマートフォンを準備
- 開発者向けオプションをonにする
- USBデバッグをONにする
- PCとデータ転送できるUSBケーブルで繋ぐ

「USBデバッグ」をONにしておらず、次項で「デバイスがみつからない」というエラーが出た。

# スマートフォン書き出し（Android）
- File > Build and Run

自動で書き出しが行われ、APKをアンドロイドに転送、実行してくれる。
インストールされたのでUSBケーブルを外しても動く。

# 最後に
作ったアプリはサンプル通りなので大したことはしていないのだけど、目の前で自分のスマホで動くっていうのは格別の喜びがある。
【徒然なるままに】2020年最新、WEB技術の勢力図を三国志にしてみた

### 今は昔
一昔前はTwitterのScala/FacebookのReactが猛威を振るっていた時期がありましたが、
イキリ勢力の消耗戦で、最近はVue勢がかなり盛り上がっている印象を受けます。

### かつてのJQuery、それがVue

そんな予感がひしひしとします。

そこで、最新のWEB勢力図を三国志風にしてみました。
三国志の知識はマンガとゲームとWikiです、すみません。

全く知らないキッズは中田さんのYoutube大学をご覧ください。
[【三国志】第一話〜英雄たちの夜明け〜ついに授業リクエストNo.1の超大作](https://www.youtube.com/watch?v=LLvH6Flstz4)

![三国志a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533968/ccda7b9e-3205-7487-038b-3500cd8f0332.png)

### 魏
- 曹操(PHP)　…　何でもあり最強、女を侍らせる。
- 夏侯惇(Laravel)　…　ロマンチスト
- 司馬懿(Vue)　…　超現実主義、パクリもありあり

### 呉
- 孫権(Ruby)　…　なんとなく
- 陸遜(Rails)　…　堅実な感じ
- 周瑜(Angular)　…　超優秀だがぱっとしない

### 蜀
- 劉備(Scala)　…　形式(礼)に拘る、前漢(Java)の末裔
- 関羽(Playframework)　…　RESTを世に広めた貢献者
- 孔明(React)　…　革新者、新時代を拓く智彗者

### 後漢、晋は図の通りです

面白そうなので、図はクリエイティブ・コモンズ(表示—非営利—継承)にしときます。
勝手に改編(~~罵倒~~)してCCでお願いします。

Reactはreact-routerとhooksでものすごい簡単になったので、
是非、新時代を体験してください。

### 新型Reactとは

簡単に書くと、これだけです。
このアトムを融合していくだけです。

```jsx

const 関数 = () => {

  ～ステート式ES6スクリプト～

  render (
    <div>～</div>
  )

}
export default 関数
```
Python(Flask)での画像の送受信メモ

## はじめに
今回は、pythonのフレームワーク flaskでの画像の受け取り方の一つをメモします。
具体的には、画像をbase64にエンコードされた形式で受け取り、flask側でデコードして画像を復元します。
ついでに、open-cvを使用して復元した画像をグレースケールに変換して、再度base64にエンコードして返却するところまでメモします。

## ソース

使用するライブラリは下記です。

```text:requirements.txt
flask
flask-cors
opencv-python
opencv-contrib-python
```

リクエストでもらうデータは、複数枚扱いたいのでjson形式にします。

```json
[
    {
        id : 0
        Image : id4zFjyrkAuSI2vUBKVLP...(base64でエンコードされたイメージ)
    },
    {
        id : 1
        Image : k75GN/oll7KUCulSpSM/S...(base64でエンコードされたイメージ)
    }
]
```

```python:main.py
from flask import Flask, jsonify, request
from flask_cors import CORS
import cv2
import numpy as np
import base64

app = Flask('flask-tesseract-api')
CORS(app)

@app.route("/image/", methods=["POST"])
def post():
    """
    画像をグレースケールに変換する
    """

    response = []

    for json in request.json:

        # Imageをデコード
        img_stream = base64.b64decode(json['Image'])
        
        # 配列に変換
        img_array = np.asarray(bytearray(img_stream), dtype=np.uint8)
        
        # open-cv でグレースケール
        img_gray = cv2.imdecode(img_array, 0)
   
        # 変換結果を保存
        cv2.imwrite('result.png', img_before)

        # 保存したファイルに対してエンコード
        with open('result.png', "rb") as f:
            img_base64 = base64.b64encode(f.read()).decode('utf-8')
        
        # レスポンスのjsonに箱詰め
        response.append({'id':json['id'], 'result' : img_base64})
       
    return jsonify(response)

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=5000,debug=True)
```

## まとめ
複数の画像をエンコードした状態で、json形式としてflaskに送ることができました。
これで、複数枚の画像を同時に扱う機能が実装できますね。
削除したnode_modulesを再インストールする

削除したnode_modulesフォルダを再インストールしたいが、可能であるか？

結論
package.jsonにモジュールが記載されているので、再インストールは可能である。

入れたいプロジェクトフォルダ上でnpm installコマンドを打つことで、新しくnode_moduleフォルダを作成することができる。

＊自分はPCを移行する際に、node_modulesフォルダだけ移行に時間がかかったので先に削除した。
新しいPC上で、再度インストールすることにした。時間の短縮です。
パッケージ版nodeをmacからアンインストールする。

#はじめに
nodebrewをインストールするつもりが、pkg版nodeをインストールしてしまったため、削除したくなりました。

#解決法
以下のコマンドで、まずnodeの存在を確認。

```bash:terminal
User$ /usr/local/bin/node -v
v12.14.1
```
バージョンが表示されたので、やはりパッケージ版がインストールされてしまっていることがわかります。
以下のコマンドを続けて打ってください。

```bash:terminal
User$ sudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man/*/node.*}
```
これでもう一度、冒頭で確認したコマンドを打ってみます。

```bash:terminal
User$ /usr/local/bin/node -v
-bash: /usr/local/bin/node: No such file or directory
```
きちんとアンインストールできました。
Macでnvim(neovim)をFinderの「このアプリケーションから開く」や右クリックメニューで開けるようにする（iTerm経由）

# 概要

Macにて、nvim(neovim)を導入しただけでは、Finderの「このアプリケーションから開く」で利用できません。これを解決する手順を記載しています。

# 前提条件

* neovimがインストール済みであること（本例ではHomeBrewでインストールしている）
* iTermがインストールされていること

# 手順

* 「Automater」を開きます。
* 書類の種類から、「アプリケーション」を開きます。
* 検索欄から、「実行」で検索し、「AppleScriptを実行」をダブルクリック。（右側の画面に表示されます。）
* コードを下記のコードで上書きします。  

```applescript
on run {input, parameters}

	# seem to need the full path at least in some cases
	# -p opens files in separate tabs
	set nvimCommand to "/usr/local/bin/nvim -p "

	set filepaths to ""
	if input is not {} then
		repeat with currentFile in input
			set filepaths to filepaths & quoted form of POSIX path of currentFile & " "
		end repeat
	end if

	if application "iTerm" is running then
		tell application "iTerm"
			create window with default profile command nvimCommand & filepaths
		end tell
	else
		tell application "iTerm"
			tell current session of current window
				write text nvimCommand & filepaths
			end tell
		end tell
	end if
end run
```

* 名前を付けて保存します。
* 保存したファイルを「アプリケーション」フォルダへ移動します。

以上で、保存したものがFinderの「このアプリケーションから開く（その他）」から選択できるようになり、iTerm経由のneovimから開くことができます。

# ついでに、「右クリックメニュー」にneovimから開くを追加

* 「Automater」を開きます。
* 書類の種類から、「クイックアクション」を開きます。
* 「ワークフローが受け取る現在の項目」で、「ファイルまたはフォルダ」を選択する。
* 左側のメニューから「Finder項目を開く」をダブルクリック。（右側の画面に表示されます。）
* 「このアプリケーションで開く」で、上述の手順で作成したアプリケーションを選択します。
* 名前を付けて保存します。名前は「右クリックメニューに表示したい文字」にします。

以上で、Finderでファイルを選択した際の右クリックメニューからneovimが開けるようになります。



# 補足事項

iTermから開けるようにしたのは、macのTerminal.appがTrue Colorに非対応の為、True Colorを前提としたカラーテーマ（Color Scheme）が正しく表示されない為でした。
nodeをパッケージでインストールして、ほとんどのコマンドが "command not found"になったときの解決法

#はじめに
新しいMacbook Proを買ったので、早速nodeの設定をしようと思いました。
そこでnodebrewを入れるつもりが、誤ってパッケージ版のnode.jsをインストールしてしまい、ターミナルからほとんどのコマンドが使えない事態になりました。
ex. rm, ls, which など
rmも使えないため、nodeもアンインストールできなくなる事態になりました。

#原因
簡潔に書くと、nodeをインストールしたことにより、複数ファイルにパスが書かれてしまっているため、コマンドが使えなくなっていることがいえます。

nodeをパッケージ版でインストールした人ですとおそらく
```/usr/local/bin/node -v```
```/usr/bin/vi ~/.bash_profile```
などは通るのではないでしょうか。
試してみて、実行されるかどうか確認してみてください。もし実行されれば、筆者と同じ状況なので、以下の解決策が有効かもしれません。

#解決策
 ```~/.zshrc```に```source $HOME/.bashrc```を追加してください。

よくわからないようであれば、以下コピペしてお使いください。
```/usr/bin/vi ~/.zshrc``` //vimでファイルを弄る
```source $HOME/.bashrc``` //追加

#しかし
本来であればパスは一つに集約されるのが理想です。
筆者は上記の目的（nodeをアンインストール）を果たした後は、再度 ```~/.zshrc```の内容を削除しています。
あくまでも暫定的処置であることをご理解ください。
Get News Titles from Google News

Google ニュースの RSS からタイトルを取得します。

```google_news_title.rb
require 'rss'

# 検索ジャンル (以下のいづれか)
#   WORLD, NATION, BUSINESS, TECHNOLOGY, ENTERTAINMENT, SPORTS,
#   SCIENCE, HEALTH
SEARCH = 'TECHNOLOGY'

def encode_url(url)
  URI.encode url.encode('EUCJP')
end

url =
  "https://news.google.com/rss/search?q=#{SEARCH}&hl=ja&gl=JP&ceid=JP:ja"

RSS::Parser.parse(encode_url(url), true, false).channel.items.each do |item|
  puts item.title
end
```

# 実行結果
![google_news_title.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28376/d2fd3bc7-2789-e480-12a2-412be99f5efa.jpeg)


# 参考にしたページ

- [Google News Rss(API) - Qiita](https://qiita.com/KMD/items/872d8f4eed5d6ebf5df1)
xfce4のターミナルのカーソルの種類を変更する

#はじめに
太いカーソルが見づらくてシャープにしたいと思い変更しました。

#方法

```conf:.config/xfce4/terminal/terminalrc
[Configuration]
...
...
MiscCursorShape= [ ここを変更します ]
```

##次の３つの中から選ぶ
TERMINAL_CURSOR_SHAPE_BLOCK (the default)
 TERMINAL_CURSOR_SHAPE_IBEAM 
TERMINAL_CURSOR_SHAPE_UNDERLINE
OpsWorks で作成した インスタンスの データベースサーバーへの接続

Opsworksで作成したLinuxインスタンスがデータベースに接続するには、適切なドライバーパッケージをインストールするよう、アプリケーションサーバーの [Recipes] タブを編集すること

## 参考
https://docs.aws.amazon.com/ja_jp/opsworks/latest/userguide/workingapps-connectdb.html

### アプリケーションのデータベースサーバーへの接続
AWS OpsWorks スタックにより 2 つの方法でアプリケーションにDBサーバーへの情報が提供されます。

- Linux スタックでは、AWS OpsWorks スタックにより、各組み込みアプリケーションサーバーインスタンスに、アプリケーションがデータベースサーバーへの接続に使用できる接続データを含むファイルが作成されます。

- AWS OpsWorks スタックでは、各インスタンスにインストールされるスタック設定およびデプロイ属性に接続情報が含められます。
  - カスタムレシピを実装してこれらの属性から接続情報を取得し、任意の形式でファイルに配置することができます。詳細については、「アプリケーションへのデータの引き渡し」を参照してください。

#### 重要
Linux スタックでは、Amazon RDS サービス Layer をアプリケーションと関連付ける場合は、次の手順に従って、関連付けたアプリケーションサーバー Layer に適切なドライバパッケージを追加する必要があります。

1. ナビゲーションペインで [Layers] をクリックし、アプリケーションサーバーの [Recipes] タブを開ます。

2. [Edit] をクリックして **適切なドライバパッケージを [OS Packages] に追加します。** たとえば、Layer に Amazon Linux のインスタンスが含まれている場合は [mysql] を、Layer に Ubuntu インスタンスが含まれている場合は [mysql-client] を指定する必要があります。

3. 変更を保存してアプリケーションを再デプロイします。
baserCMS 初期化/再インストール手順

なんか最新のbaserの記事がなかったので一応備忘録として。

#baserCMSの再インストール手順

まず、`app/Config/install.php`の`Configure::write('debug', 0)`を-1に変更します。

その後、basercmsをインストールしているディレクトリにいき、`app/Console/cake bc_manager reset`でリセットされます。

その後ブラウザでアクセスするだけでインストール画面に行きます。簡単ですね。



また、その後再インストールする際は
```app/Console/cake bc_manager install {インストールするurl} {dbの種類(mysql)} {管理者ユーザ名} {管理者ログインパスワード} {管理者メールアドレス} --host {dbのホスト} --database {使用するdbの名前} --login {dbのユーザ名} --password {dbのパスワード} --prefix mysite_ --port {使用するポート名} --baseurl {基本url、インストールするurlと同じでいいです}```

でもできます。長ったらしいですね。対話形式のシェルでも作ろうかな
AWS 認定Developer Associate に合格するまで


# はじめに

この記事では、いかにして私が2週間ほどの勉強期間でデベロッパーアソシエイトの認定を合格したのかを紹介いたします。

# 動機

今までの業務ではAWSを主に分析やETL処理といった用途で扱ってきたが、新しい業務ではAWSの基本的なサービスを抑える必要がありました。

そこで、AWSの勉強の１つのマイルストーンとして認定試験の合格とし、勉強をはじめました。

# 経歴

私は業務でデータエンジニア、データサイエンティストといった職種の業務を担当することが多く、触ったことがある AWSサービスはかなり偏っておりました。
(もちろん他のAWS認定資格は持ち合わせておりません)

ちなみに勉強を始める以前に使ったことのあるサービスは以下になります。

- S3
- AWS Athena
- EMR
- EKS
- AWS QuickSight
- AWS CodeBuild
- AWS Glue
- AWS ECS

分かる人はわかるかもしれませんがこの中で認定試験で頻出するサービスはS3とCodeBulidくらいで、正直0からのスタートといっても過言ではありませんでした。

特にDeveloper Associateの問題で頻出のLambdaやDynamoDBすらも触ったことがありませんでした。



# 勉強方法

## 1. 対策本を読む

まずはAWSのサービスの全体像を抑えるために認定試験の対策本を読書いたしました。

読んだ本は以下になります。

**AWS認定アソシエイト3資格対策~ソリューションアーキテクト、デベロッパー、SysOpsアドミニストレーター~**
https://www.amazon.co.jp/dp/4865941991

サービスごとにポイントが解説されているため、知識を整理しやすかったです。



## 2. サービスごとのポイントを自分なりに整理してアウトプットする

対策本を読むことである程度知識をインプットできたので、次にアウトプットを行いました。

自分なりに各サービスのポイントをまとめてノートのようなものを作成いたしました。

そのときの成果物が以下になります。

- [【AWS認定試験対策】EC2のポイントまとめ](https://qiita.com/yoshiyama_hana/items/1fef71430f11729a56e2)

- [【AWS認定試験対策】VPC、Route53のポイントまとめ](https://qiita.com/yoshiyama_hana/items/fd087f9a19538b8f6667)

- 【AWS認定試験対策】DBサービスのポイントまとめ(Qiitaにて執筆中)

- 【AWS認定試験対策】Lambdaのポイントまとめ(Qiitaにて執筆中)

- 【AWS認定試験対策】その他サービスのポイントまとめ(Qiitaにて執筆中)

  

## 3. 模擬試験を受験する

本番の試験問題の雰囲気を知ることと自分が今何が苦手なのかを知ることを目的として、模擬試験を受験いたしました。上司の進言で他のアソシエイトレベルの模擬試験も受験することをすすめられたのでアソシエイトレベルのものをすべて受験いたしました。

そのときの結果がこちらです。合格ラインは72%です。

- Developer - Associate：70%(不合格)
- Solution Architect - Associate：75%(合格)
- SysOps Administrator - Associate：75%(合格)

自分が受験するデベロッパーアソシエイト以外が合格という結果でした。

ちなみに模擬試験では問題の正答が公表されておらず、自分がどの分野(セキュリティの分野やデプロイメントの分野など)でどのくらい正答したのかがわかります。

このとき、私はスクショを撮ってどの問題を誤答したのか分析して復習しました。

たしか、ElasticBeanstalkのデプロイメント方式を全然理解できていなかったり、Lambdaのリトライ方式について把握し切れていなかったことがわかり急いで勉強した記憶があります。



## 4. 問題集を解く

最後に以下のサイトの問題集を解いて仕上げました。

https://aws.koiwaclub.com/

誤答したらなぜ間違えたのかすぐにフィードバックされるのがよかったです。



# 試験本番

試験は約60問を120分間で解きます。

つまり、2分で1問のを解くということになりますが、すべて選択問題であるためそんなに時間に迫られたといった印象はありませんでした。

私は3周見直しをして60分余り、これ以上やっても結果が変わらないと判断し終了しました。



# 結果

合否の結果は試験終了直後にPCの画面に表示されます。

結果は合格でした。

数時間するとAWSの認定アカウントにスコアが載ります。

私の結果は1000点中、805点でした。(合格ラインは720点)



# 感想

当初の狙い通り、認定資格の合格を目標とすることでAWSの基本的なサービスのポイントを抑えられた実感があります。

以前はちんぷんかんぷんだった同僚の技術的な話にも少しずつついていけるようになりました。

また、自分の使っているサービスでも改めて客観的に勉強してみることで新たな気付きにつながりました。

例えば、以前はこうやってETL処理基盤を構築したけど今思えば密結合だよな。。。だとか考えられる幅が変化しました。



しかし、認定資格を合格したからといってどんどん新しい業務ができるようになった！！というわけではありませんでした。

やはり、サービスを「知っている」と「触ったことがある」の違いはとても大きいように感じます。

ですので、認定合格した際には是非知らなかったサービスを自分の手で触ってみることをおすすめいたします。
Angular９とFirebaseでブログを作ってみる９（Analyticsを使ってみる）

[前回](https://qiita.com/teracy55/items/71c84c59100bd312044c)、Twitterのタイムラインを組み込んでみました。

TOPページだけはそれっぽくなってきたので、ここらへんでAnalyticsを組み込んでみようかと思います。


# AngularFireでのAnalytics

[手順](https://github.com/angular/angularfire/blob/master/docs/analytics/getting-started.md)があるので、その通りに導入してみます。

※angular/fireの設定は[こちら](https://qiita.com/teracy55/items/ac9f83c1fcac589b876b#angular%E3%81%8B%E3%82%89firebase%E3%82%92%E5%8F%82%E7%85%A7%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E8%A8%AD%E5%AE%9A)を参照

## AngularFireAnalyticsModuleのインポート

- app.module.tsを修正します
    - AngularFireAnalyticsModuleのインポート
    - ScreenTrackingServiceのProvide（[参考](https://github.com/angular/angularfire/blob/master/docs/analytics/getting-started.md#tracking-screen-views)）

```src/app/app.module.ts
・・・
import { AngularFireAnalyticsModule, ScreenTrackingService } from '@angular/fire/analytics';

@NgModule({
 ・・・
  imports: [
  　・・・
    AngularFireAnalyticsModule,
  　・・・
  ],
  providers: [
    ScreenTrackingService
  ],
```

これだけでアクセスのトラッキングができるみたいです。


# こんな感じになりました

Firebaseのコンソールからアクセスが確認できるようになりました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/894d56d7-0592-5ff6-51a4-51864c0fdc29.png)


angular/fire使うと簡単で良いですね

次回：[Angular１０ とFirebaseでブログを作ってみる１０ （flex-layoutでレスポンシブ対応してみる）](https://qiita.com/teracy164/items/b78bdc6339d3f814752e)
Firebase Authenticationで認証コードログインを実現する

# やりたいこと
- 個人ごとにユーザ管理したりするほどの要件ではない
- かといってサイトにアクセスできた人全員が使えてしまうのは困るので簡易ログインはほしい
- ログイン機能は自分では実装したくない

→「認証コード」を使ったログイン機能をFirebase Authenticationで実現したい

# できたもの
![ezgif.com-resize.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149212/00c64364-3243-5542-93fd-bb92976ed281.gif)


# ４行で
1. 匿名認証してUIDをゲット
2. 1のUIDと入力された認証コードをCloud Functionsに投げる
3. 認証コードが正しければ2のUIDにCustom claimを付与
4. 以後のログインチェックはCustom claimで判定

# フロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149212/7728779e-4316-fff6-dc89-03e0fbca7397.png)

# 実装
本記事はJSで実装していますが言語は特に重要ではないため、その他の言語でも同じように実装できると思います。要所を抜粋しているので単純にコピペしても動作しません。

## フロントエンド
①〜④、⑧の部分です。

``` login.js
// 匿名認証でログインしてUIDを取得
const userCredential = await firebase.auth().signInAnonymously()
const uid = userCredential.user.uid

// 認証コードが正しければそのユーザーにカスタムクレイムを付与する関数を呼び出し
const authWithCode = firebase.functions().httpsCallable('authWithCode')
const result = await authWithCode({ uid, verifyCode: this.code })
// カスタムクレイム付与後、強制的にトークンをリフレッシュ
await firebase.auth().currentUser.getIdToken(true)
```

Vue.jsのrouterを使用する場合は以下のようにログイン判定ができます。

``` router.js
firebase.auth().onAuthStateChanged(async function (user) {
  if (user) {
    let getIdTokenResult = await user.getIdTokenResult()
    if (getIdTokenResult.claims.codeVerified) {
      // カスタムクレイムで認証成功したとき
      next()
    } else {
      // 匿名認証はしているけどカスタムクレイムが付与されていないとき
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    }
  } else {
    // 匿名認証すらしていないとき
    next({
      path: '/login',
      query: { redirect: to.fullPath }
    })
  }
})
```


## コード検証関数
⑤〜⑦の部分です。

``` codeVerify.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

const VERIFY_CODE = '0112'

exports.authWithCode = functions.https.onCall(async (request, response) => {
  // 設定された認証コードと送られてきた認証コードが一致するか判定
  if(request.verifyCode === VERIFY_CODE) {
    try{
      // Custom claimを付与
      await admin.auth().setCustomUserClaims(request.uid, {codeVerified: true})
      return { status: 'ok', message: '認証しました。' }
    }catch(error){
      return { status: 'error', message: 'ログイン処理に失敗しました。' }
    }
  }else{
    return { status: 'error', message: '認証コードが正しくありません。' }
  }
});
```

## Firestoreルール
データソースのルールはCustom claimで判定するようにするとコード認証したユーザーのみ操作が許可できます。

``` rule.js
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read: if request.auth.token.codeVerified == true;
      allow write: if false;
    }
  }
}
```

# 参考
[公式]Custom claimについて
https://firebase.google.com/docs/auth/admin/custom-claims?hl=ja#best_practices_for_custom_claims
https://firebase.google.com/docs/auth/admin/custom-claims?hl=ja

Callable HTTPS Functionについて
https://miso-soup3.hateblo.jp/entry/2018/05/22/215453
Rails consoleで別のテーブルの_idとの結び付け

##今回はRailsコンソール
を使ってトークルームにカテゴリーを紐付ける際に、初歩的なミスで試行錯誤するはめになってしまったので、メモとして残したいと思います。

まずは、コンソールで入力した結果を先に表示したいと思います。

2.5.3 :001 > user = User.first
   (7.5ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  User Load (0.2ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
 => #<User id: 1, name: "テスト先生", email: "test@test.com", password_digest: "$2a$12$bE/ULSzcgeZBWMqsaFsEGuQ/6VZZP2oxS2iuvQ6i7uj...", introduction: "よろしくお願いします。", picture: nil, post_a_picture: nil, post_b_picture: nil, created_at: "2020-01-25 08:39:21", updated_at: "2020-01-25 08:39:21"> 
2.5.3 :002 > memo_room = user.memo_rooms.build(title: 'hello')
 => #<MemoRoom id: nil, title: "hello", user_id: 1, category_id: nil, created_at: nil, updated_at: nil> 
2.5.3 :003 > category = Category.first
  Category Load (0.2ms)  SELECT  `categories`.* FROM `categories` ORDER BY `categories`.`id` ASC LIMIT 1
 => #<Category id: 1, title: "hello", user_id: 1, created_at: "2020-01-25 13:52:19", updated_at: "2020-01-25 13:52:19"> 
2.5.3 :004 > memo_room = user.memo_rooms.build(title: 'hello', category_id: category.id)
 => #<MemoRoom id: nil, title: "hello", user_id: 1, category_id: 1, created_at: nil, updated_at: nil> 
2.5.3 :005 > memo_room.save
   (0.3ms)  BEGIN
  Category Load (0.3ms)  SELECT  `categories`.* FROM `categories` WHERE `categories`.`id` = 1 LIMIT 1
  MemoRoom Create (0.2ms)  INSERT INTO `memo_rooms` (`title`, `user_id`, `category_id`, `created_at`, `updated_at`) VALUES ('hello', 1, 1, '2020-01-26 10:24:56', '2020-01-26 10:24:56')
   (2.7ms)  COMMIT
 => true 
2.5.3 :006 > 

_____________________________________________________________________

・まず最初にuser = User.firstで　最初のユーザーを表示します。

・次にmemo_room　←トークルームと考えてください。にuser.memo_rooms.buildでタイトルhelloを作成します。

・これで、memo_roomのタイトルが作成されました。

・次に、このmemo_roomにはcategoryが紐づいているので、今の状態だとcategoryが紐付けされていないのでsaveは出来ません。
errorメッセージ表示をすると、categoryが必須です。と出ている状態です。(memo_room.errors.full_messages←で設定してあるのでコンソールに入れるとcategoryが必要な表示が出ます。)

・次にcategoryが作成されていなかったので、category(カラムはtitle)　←カテゴリを同じように作成します。（流れ同じなので略）

・そしてmemo_room = user.memo_rooms.build(title: 'hello', category_id: category.id)
memo_roomにcategory_idを入れてあげます。　category_idは数字であり文字列ではないので''は使いません。

#上記の時に、memo_room　←の変数に代入を忘れていました。
ただcategory_idを入れてるだけを繰り返し。無意味に悩んでいたのです。

user.memo_rooms.build(title: 'hello', category_id: category.id) ←変数なしでただ作ってるという意味ない事をしてました。

変数にきちんと入れれば、　usersテーブル、memo_roomsテーブル、categoriesテーブルの3つのidが入り。
きちんと紐付けされて結果saveが上手くいきました。

初歩的なミスですが、メモを残す事によって、久しぶりにやった際に忘れないようにという思いで書きました。