OmniAICreator/Qiita-1.07M huggingface dataset:
Python3でJSONのキーだけを再帰的に変換する

# 🥚やりたいこと

JSONファイルの**キー（=プロパティ）だけ**を別の文字表現に変換したい。
具体的に言うと、例えば、以下のようなJSONファイルがあるとする。

```json
{
    "abc": 1,
    "def": {
        "def_abc": 2,
        "def_def": 3
    },
    "ghi": [
        "abc",
        "def",
        [
            {
                "ghi_abc": 4
            }
        ]
    ]
}
```

上記のJSONファイルを、以下のようにキーのみを大文字にしたり、

```json
{
  "ABC": 1,
  "DEF": {
    "DEF_ABC": 2,
    "DEF_DEF": 3
  },
  "GHI": [
    "abc",
    "def",
    [
      {
        "GHI_ABC": 4
      }
    ]
  ]
}
```

キャメルケースに変換したりしたい。

```json
{
  "abc": 1,
  "def": {
    "defAbc": 2,
    "defDef": 3
  },
  "ghi": [
    "abc",
    "def",
    [
      {
        "ghiAbc": 4
      }
    ]
  ]
}
```

この時に、ちゃんとネストの中のオブジェクト（上記で言うと`{"ghi_abc": 4}`のような）のキーもちゃんと変換できるようにするほか、単なるリテラルやリストには変換の影響がないようにしたい。

#🐣やってみたこと

以下のようなPythonスクリプトで変換処理を実装してみた。

```python
import json

def convert(data, func=lambda x: x):
    if isinstance(data, dict):
        obj = {}
        for key, value in data.items():
            obj[func(key)] = convert(value, func)
        return obj
    elif isinstance(data, list):
        obj = []
        for item in data:
            obj.append(convert(item, func))
        return obj
    else:
        return data

def to_uppercase(str):
    return str.upper()

def to_camelcase(str):
    arr = str.split('_')
    return arr[0] + ''.join(x.title() for x in arr[1:])

def main():
    with open('input.json', 'r') as input_file, open('output.json', 'w') as output_file:
        json_obj = json.load(input_file)
        converted = convert(json_obj, to_camelcase)
        json.dump(converted, output_file)

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

### JSONのキーを再帰的に変換する

```python
def convert(data, func=lambda x: x):
    if isinstance(data, dict):
        obj = {}
        for key, value in data.items():
            obj[func(key)] = convert(value, func)
        return obj
    elif isinstance(data, list):
        obj = []
        for item in data:
            obj.append(convert(item, func))
        return obj
    else:
        return data
```

この関数でJSONのキーを再帰的に変換している。
最初のif分岐で辞書か配列かそれ以外か判別し、以下のような処理を行う。

- 辞書の場合 ... 辞書内の項目を順に見ていき、それぞれの項目のキーを変換する。値は再帰的にconvertへ引き渡す。
- 配列の場合 ... 配列の項目を順に見ていき、その項目を再帰的にconvertへ引き渡す。
- それ以外　 ... そのまま返す。

ちなみに、この実装は以下のように簡潔に書ける。

```python
def convert(data, func=lambda x: x):
    if isinstance(data, dict):
        return {func(key): convert(value, func) for key, value in data.items()}
    elif isinstance(data, list):
        return [convert(item, func) for item in data]
    else:
        return data
```

実際にキーをどう変換するかの処理は引数の`func`に委譲している。

#🐥まとめ

- `json.load()`で読み込んだJSONファイルをPythonオブジェクトに読み込んだ際、dict/list/その他で判別するだけで問題ないのだろうか。
- 公式ドキュメントの[変換表](https://docs.python.org/ja/3/library/json.html#json-to-py-table)を見る限り問題なさそうだが……。
- パイソニスタのレビュー・マサカリを頂ければ幸いです。
🐳 Docker で Django のロケットを表示する 🚀

# Docker をインストール

https://www.docker.com/

# 適当にディレクトリを作って入る

```
mkdir ~/django_test
cd django_test
```

# Dockerfile を作る

```
touch Dockerfile
```

# Dockerfile を編集する

以下をコピペする

```Dockerfile
FROM ubuntu
RUN apt-get -y update && \
    apt-get -y install \
        python3 \
        python3-pip \
        vim
RUN pip3 install \
        django
```

# 作った Dockerfile をもとに Docker image 生成

```
docker build . -t django3
```

# ちゃんと Docker image ができてるか確認

```
docker images
```

↓ こんな感じのが出力されれば OK

```
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
django3             latest              ae2afa4d1190        45 seconds ago      459MB
```

# コンテナを生成して入る

ついでにボリュームのマウントとポートフォワーディングの設定をする

```
docker run -it -v $(pwd):/code -p 8000:8000 --name django_test django3 /bin/bash
```

ちょっと長いけど分解して見れば意外とシンプル

`docker run django3` がベースのコマンドで、それに 4 つのオプションがついてるだけ

- `-it /bin/bash` でコンテナに入る
- `-v $(pwd):/code` で今いるディレクトリをコンテナ内の `/code` と共有する
- `-p 8000:8000` でホストのポート 8000 とゲストのポート 8000 をポートフォワーディング
- `--name django_test` でコンテナに名前をつける

上のコマンドを実行して `root@~` みたいなのがプロンプトに表示されれば OK

# ちゃんと Python と Django がインストールされてるか確認

コンテナ内で以下を実行

```
python3 --version
    -> Python 3.8.2 
python3 -m django --version
    -> 3.0.8
```

# startproject する

```
cd /code
mkdir django_test
cd django_test
django-admin startproject django_test
```

# settings.py を編集する

`settings.py` の `ALLOWED_HOSTS` に `0.0.0.0` を追加する

```python
ALLOWED_HOSTS = ['0.0.0.0']
```

# runserver する

`manage.py` があるディレクトリに移動してから以下を実行

```
python3 manage.py runserver 0.0.0.0:8000
```

# ブラウザでロケットを確認

ブラウザで http://0.0.0.0:8000/ にアクセスする
ロケットが飛んでれば OK!! 🚀

![djangorocket.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238922/12527292-0195-a616-7f18-aef2c20614d7.png)
ローカルのエラーを解決しても本番環境で反映されなかった件(DBが原因だった編)


#最初に#
フリマアプリのコピーをチームで開発している時、ローカル環境で下記エラーが出ており、

```rails db:dorop``` 

```rails db:create``` 

```rails db:migrate```

をしたら解決できました。
しかし、本番環境ではDBの状態が古いままだった為、ずっとエラーが起きている状態でした。

<img width="1421" alt="q1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677058/c2c3ba18-82a1-6097-0379-1da01b72cb39.png">

#間違った理解#

カリキュラムを見直すと本番環境用のコマンドをcurrentディレクトリで実行しなけばならないことが分かりました。
しかし、ec2にSSH接続した後、リポジトリ名に移動することがcurrentディレクトリのことだという間違った解釈をしていたのです。←今考えると意味不明...

#解決#

```cd current/```

にてcurrentディレクトリに移動。

```DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop```

```rails db:create RAILS_ENV=production```

```rails db:migrate RAILS_ENV=production```

でDBを新しく作り直すことができ無事エラーが解消、本番環境でtop画面を表示させることができました!
ログイン画面作成（備忘録）　section71（完）

エラーチェックが終了したら入力確認画面に遷移する動作を実現したい。

エラーチェックプログラムの一番最後に以下のコードを記述する。

```
header('Location: check.php');
exit();
```

header('Location: check.php');は check.phpに飛んで、index.phpをexit()します。

現状では、無条件にcheck.phpに移動してしまいます。
移動する条件は記入された文字にエラーがないことになります。

```
if(empty($error)){
	header('Location: check.php');
	exit();
}
```
＞＞$errorに値が格納されていない時（空の場合）、check.phpに飛ぶことにする。

まだこの時点でも不十分。

index.phpを直接呼び出すとパスワードにエラーが表示されています。
呼び出された時点でプログラムが走ってしまうのでプログラムの走る条件を
「入力確認ボタンが押された時」にします。
先頭に以下のコード記述する。

```
if(!empty($_POST())){
	エラーチェックコード
}
```
＞＞$_POST()が空じゃない時にエラーチェックコードを走らせる
つまり、フォーム送信が行われた時（ボタンが押された時）にエラーコードを走らせる。
（index.phpが呼ばれたときはフォーム送信が行われていない）
.NET 5での気づきを記録していくメモ

おもに「.NET Frameworkではできてたけど.NET 5に移行して実装の修正が必要となった」点について気づきを記録していきます。.NET Frameworkで実装した既存資産を、.NET 5に移行する際の注意点を具体化できればいいかなと思います（ほとんど書くことないかも…）。

なお、この記事は育てる記事なので随時追記予定。

## ファイルのアクセスコントロール

[File.GetAccessControl](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.file.getaccesscontrol?view=netframework-4.8)は、.NET 5では使用できないため、[FileInfo.GetAccessControl](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.fileinfo.getaccesscontrol?view=netframework-4.8)を使用します。事前にNuGetパッケージ`Sysem.IO.FileSystem.AccessControl`のインストールが必要です。

```csharp:ファイルのアクセスコントロールにEveryone・FullControlを付与
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var info = new FileInfo(@"C:\usr\local\sample.txt");
            var security = info.GetAccessControl();

            security.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                FileSystemRights.FullControl, AccessControlType.Allow));
            info.SetAccessControl(security);
        }
    }
}
```

【参考】[Add “Everyone” privilege to folder using C#.NET](https://stackoverflow.com/questions/5298905/add-everyone-privilege-to-folder-using-c-net)

## Rijndaelのブロック長

Rijndaelのブロック長について、.NET Framwrokでは**128 ビット**または**256 ビット**を指定可能でしたが、.NET Coreからは**128 ビット固定**です。

```csharp:
using (RijndaelManaged rdm = new RijndaelManaged())
{
    //rdm.BlockSize = 256; // System.PlatformNotSupportedException: BlockSize must be 128 in this implementation.
    rdm.BlockSize = 128;
```

【参考】[256 blocksize does not work in .net core #13](https://github.com/2Toad/Rijndael256/issues/13)
linux: オリジナルのTerminal コマンドを作成

### 結論のみ
command.shを作成して、functionを記述
.bashrcを開いて、`source ${path-to-command.sh}/command.sh` を追記
以下、詳細


### 1 基本
```.sh:terminal
# terminal を開く
# 以下入力(shift + Enterで改行)
user@pop-os:~$ function test() {
> echo $1
> }

# 定義した関数を呼び出し
user@pop-os:~$ test "hello bash script"
hello bash script
```
> 簡単。でも、一度terminalを閉じると、もう使えなくなる

### 2 関数をファイルに保存
```.sh:terminal
# rotate.sh を作る
user@pop-os:~$ mkdir commands
user@pop-os:~$ vim commands/rotate.sh
```

```.sh:rotate.sh
#!/bin/bash
# rotate screen
function rotate() {
  case $1 in
    # left
    [lL])
        xinput set-prop 13 'Coordinate Transformation Matrix' 0 -1 0 1 0 0 0 0 1
        xrandr -o left
	;;
    # right
    [rR])
	xinput set-prop 13 'Coordinate Transformation Matrix' 0 1 0 -1 0 0 0 0 1
	xrandr -o right
	;;
    # upside down
    [bBdD])
	xinput set-prop 13 'Coordinate Transformation Matrix' -1 0 0 0 -1 0 0 0 1
	xrandr -o inverted 
	;;

    # normal
    *)
        xinput set-prop 13 'Coordinate Transformation Matrix' 1 0 0 0 1 0 0 0 1
        xrandr -o normal
	;;
  esac
}
```
> \#はコメント。
$1 は第一引数。
case は、switch文で、引数の値が、続く正規表現に一致するときだけ実行。
`[lL]`は正規表現で、小文字のlか大文字のLかどちらか。
)はcase文の１ケースであることを示す。
;;はbreak。
esacはcaseの終わりタグ。
xinput set-propとxrandrは、画面を回転させて、マウスの入力方向を回転させている。詳しくは、別記事参照。

これだけでは、当然関数は使えないので、bashに関数を読み込む必要がある

```.sh:terminal
user@pop-os:~$ rotate
rotate: command not found
```

### 3 bashに作成した関数を読み込ませる

```.sh:terminal
# bashに関数を追加
user@pop-os:~$ source ~/commands/rotate.sh
# 関数を実行
user@pop-os:~$ rotate l
```
> 簡単。ターミナルを閉じると、また`source`を実行しないといけない。そこで、.bashrc(bash run control) に、関数を呼び込む処理を書く必要がある

### 4 .bashrc (bash run control) に、作成した関数を追加
```.sh:terminal
user@pop-os:~ sudo vim ~/.bashrc 
```
一番下の行に以下を追加

```.shell:.bashrc
# オリジナルのコマンドを読み込み
source ~/command/*.sh
```

これで、未来永劫、コマンドが使えるようになる

```.sh:terminal
user@pop-os:~ rotate r
```
ログイン画面作成（備忘録）　section71（序）

section70のままだと記入したのに
エラーが起こるごとに消えてしますので
記入した内容は次に再現するようにしていきたい。

これはつまり、テキストフィールドの初期値を設定すれば良い。
テキストフィールドの初期値は

```
　<input type="text" name="email" size="35" maxlength="255" value="" />
```
のvalueの部分を

value="<?php print($_POST['name']);?>"にすれば入力された値はテキストフィールドに入る。
しかし、HTMLには特殊文字があり、このままでは入力した文字によって予期せぬ
誤動作を捨可能性がある。これを防ぐためにhtmlspecialchars()を使用する。

```
value="<?php print(htmlspecialchars($_POST['name'],ENT_QUOTES));?>"
```
詳細は検索：https://www.php.net/manual/ja/function.htmlspecialchars.php　

今回書いたニックネームのチェックコードを同じように
メールアドレス、パスワードに変えて記述していく。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

次にパスワードのチェックを記述していく。
現在の状態だと、１文字だけでもOKの状態なので非常に危険な状態です。

最低文字数に制限をかけてチェックしていく
検査順は「空欄があるかどうか」のチェック項目の前でしていく

```
if(strlen($_POST['password'] < 4)){
	$error['password'] = 'length';
}
```
strlenは指定した文字数を測って数字で返してくれる
$_POST['password']に入ってきた文字数が４未満の場合、エラーコード（length）を格納する。

そしてエラーを表示させたい場所に以下のコードを記述していく。

```
<?php if($error['password'] === 'length'): ?>
	<p class=error>※パスワードの文字数は４文字以上にしてください</p>
<?php endif; ?>
```

続　））
Spring振り返り メモ



## はじめに
「Spring Framework 徹底入門」を読み返すにあたって、各章の見出しを書き出したもの。

詳細は↓ の書籍を参照

<a target="_blank"  href="https://www.amazon.co.jp/gp/product/B01IEWNLBU/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B01IEWNLBU&linkCode=as2&tag=zipangsky-22&linkId=4178f5ee2080d50435a295e1b8579c77"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=B01IEWNLBU&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL160_&tag=zipangsky-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=zipangsky-22&l=am2&o=9&a=B01IEWNLBU" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />


# CHAPTER 1 Spring Framework とは
Spring Framework の概要と歴史

# CHAPTER 2 Spring Core (DI x AOP)
Spring のコア機能の解説
## DI（Dependency Injection）
コンポーネントを構成するインスタンの生成と依存関係の解決をソースコードから分離する。
DIコンテナを経由してインスタンスを管理する。
・インスタンスのスコープを制御できる
・インスタンスのライフサイクルを制御できる
・共通機能を組み込める
・コンポーネント間が疎結合になるため、単体テストがしやすくなる

Spring Framework 以外の有名なDIコンテナフレームワーク
・CDI(Contexts & Dependency Injection)
・Google Guice
・Dagger

## AOP（Aspect Oriented Programming）
「横断的関心事の分離（Separation Of Cross-Cutting Concerns）」を実現するためのアスペクト思考プログラミング。

Springプロジェクトで使用されているAOP
・トランザクション管理
・認可処理
・キャッシュ処理
・非同期処理
・リトライ処理

### データバインディングと型変換
### プロパティ管理
アプリケーション内で使用する設定値を解決する仕組みについて。
### Spring Expression Language (SpEL)
Spring Expression Language (SpEL) は、Spring Framework が提供しているExpression Language。
### リソースの抽象化
リソースへのアクセス方法
### メッセージ管理
メッセージの管理諸々（多言語サポート）

# CHAPTER 3 データアクセス(Tx,JDBC)
Spring が提供するデータアクセス支援機能のSpring JDBCについて。
・アプリケーション内に定義したデータソース
・アプリケーションサーバーに定義したデータソース
・組込みデータベースのデータソース

・JdbcTemplate クラスを利用したCRUD操作
・トランザクション管理
・データアクセスエラーのハンドリング

# CHAPTER 4 Spring MVC
Spring MVC を利用したWebアプリケーションの開発方法。
・POJO (Plain Old Object) での実装
・アノテーションを使用した定義情報の指定
・柔軟なメソッドシグネチャの定義
・Servlet API の抽象化
・View の実装技術の抽象化
・Spring の DIコンテナとの連携

# CHAPTER 5 Webアプリケーションの開発
Webアプリケーション開発に必要となるコンポーネント（Controller、フォームクラス、Viewなど）の詳細。
・アプリケーションの設定
・＠Controllerの実装
・リクエストマッピング
・リクエストデータの取得
・フォームクラスの実装
・入力チェック
・画面遷移
・Viewの解決
・JSPの実装
・Spring のHTMLフォーム用タグライブラリの利用
・Spring の汎用タグライブラリの利用
・例外ハンドリング

# CHAPTER 6 RESTful Web サービスの開発
RESTful Webサービス（REST API）の開発について。
・REST API のアーキテクチャ
・アプリケーションの設定
・＠RestController の実装
・リソースクラスの実装
・例外ハンドリング
・REST クライアントの実装

# CHAPTER 7 Spring MVC の応用
・HTTP セッションの利用
・ファイルアップロード
・非同期リクエストの実装
・共通処理の実装
・静的リソース
・国際化

# CHAPTER 8 Spring Test
Springアプリケーションに対してテストを行う方法。

# CHAPTER 9 Spring Security
Webアプリケーションに対してセキュリティ対策を行う方法。
・認証機能
・認可機能

・セッション管理機能
・CSRF対策機能
・ブラウザのセキュリティ対策機能との連携機能

・Spring Security のテストの方法

# CHAPTER 10 Spring Data JPA
Spring Data JPA の機能を使用してJPA (Java Persistence API) を用いる方法。

# CHAPTER 11 Spring + MyBatis
Spring + MyBatis の利用方法。
・MyBatis でのCRUD操作（基礎・応用）

# CHAPTER 12 Spring + Thymeleaf
View にJSP ではなくThymeleaf を使用する方法。

# CHAPTER 13 Spring Boot
Spring Boot を使うと、Java Config によるBean定義、ログの設定、Servlet の設定が不要になる。
さらに、アプリケーションサーバーへのデプロイも必要なくなる。
【初心者】マイグレーションファイルを修正したい　-ロールバックの使い方-

私は勉強し始めた最初の頃、自分で何かを作ろうとして間違えたらすぐに消していました。
特にやらかしてしまうのはmigration周り…
そんないつも消してしまっている方にぜひ使ってもらいたいのがrollbackです。

###rollback(ロールバック)とは
巻き戻し
コミットする前までの処理を１つづつ戻すことができること

### 使い方
あ、間違えてしまったと思った時は、
まずは現状を見ます。

```
$ rails db:migrate:status
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     　日付  　　　　　Devise create users
   up     　日付 　　　　　 Add name to users
   up     　日付  　　　　　Create posts
```
upの状態だとマイグレーションファイルを編集しても読み込めれません。
そこで、


```
＄ rails db:rollback
```
```
$ rails db:migrate:status
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     　日付  　　　　　Devise create users
   up     　日付 　　　　　 Add name to users
  down      日付  　　　　　Create posts
```

状態をdownにすることで編集することができます。
同時に複数のマイグレーションファイルをrollbackさせたい時は

```
＄ rails db:rollback　STEP=2
```
```
$ rails db:migrate:status
 Status   Migration ID    Migration Name
--------------------------------------------------
  down      日付  　　　　  Devise create users
  down      日付 　　　　　 Add name to users
  down      日付  　　　　　Create posts
```

このようになります。
downの状態にした後に修正をし、再度rails db:migrateコマンドを実行します。

ちなみに最初からやり直したい時は

```
＄ rails db:rollback　VERSION=0
```

###まとめ
初めは、間違えたら消した方が早いと思うのですが、これを覚えるだけでかなり気持ちが楽になります。
【グラレコ風読書メモ】『データマネジメントが30分でわかる本』を読んで

## 『データマネジメントが30分でわかる本』とは

[『データマネジメントが30分でわかる本』](https://amzn.to/3fIuty5)は、[ゆずたそ](https://twitter.com/yuzutas0)氏とはせりょ氏が、プロジェクトマネジメントにおけるPMBOKのデータ管理版、[DMBOK(データマネジメント知識体系)](https://amzn.to/30oVLTY)を、ご自身の業務経験に照らして要約、事例を加えてわかりやすく解説された本です。
Kindle版と紙版があり、Kindle版はKindle Unlimited対象にもなっていました。(2020/7/19現在)

各知識体系について、具体度を徐々に上げる構成で、網羅的に解説されています。抽象的(30秒コース)を一気に通読するか、ひとつひとつの項目をケーススタディ(3時間コース)まで掘り下げながら進むかは、読者に委ねられています。

- **30秒**コース「一言で」
- **3分**コース「なにそれ」
- **30分**コース「どうして、ゴール、具体的にどうする」
- **3時間**コース「ケーススタディ」

著者の経験に基づく解釈が入っているおかげで、抽象化のため、そのままでは読みづらくなりがちな知識体系と比べ、実務の手触りを感じながら読み進めることができます。

先日話題となっていたゆずたそ氏の講演資料([Data Platform Guide - 事業を成長させるデータ基盤を作るには #DataEngineeringStudy / 20200715 - Speaker Deck](https://speakerdeck.com/yuzutas0/20200715))がきっかけで、この本を知り、手に取りました。

## データマネジメント、DMBOKとは
### データマネジメント

引用します。

> データマネジメントとは、文字通り、データを管理することです。
> 
> ただし、ひとくちに「管理」といってもその内容は幅広いです。主要な業務としては、データを登録・更> 新・活用することが挙げられます。
> -- [データマネジメントとは何か](https://jp.drinet.co.jp/blog/datamanagement/oldxmsgcebbvw)

以前紹介した[メルカリ「機械学習システムの設計パターン」](https://qiita.com/tomo_makes/items/df5375363cb14f937b75)がデータ活用フェーズ、かつ機械学習アプローチとすると、その前におさえておくべきデータ蓄積、整備のために必要な技術、プロセス両面がフレームワークとして整理されています。

### DMBOK

DMBOK(Data Management Body of Knowledge)は、業務要件に寄り添い、データ管理の仕組みを定め、継続的に改善していくために何に気をつけたら良いか、をフレームワークとしてまとめて提示してくれています。
DMBOK自体はこんな姿をしています。これを実例を含め読み解いていくと、以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/815bfe16-2362-8d00-f7e0-05b7470f71d3.png)

> 出典: [DMBOKポータル | 株式会社データ総研](http://www.drinet.co.jp/dmbok)


## ざっくりまとめ

1回目のざっと通読ですが、自分の2回目以降、あと人と話をするときのため、簡単なサマリを作りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/b8c36bea-74b4-bb81-9983-2cf9c0975345.png)

この本では、DMBOKの並び順も、整理のため以下のようにフェーズごとに再構成されています。

- **プランニング**
    - データアーキテクチャ
- **実装・運用（システム編）**
    - データストレージとオペレーション
    - データ統合と相互運用性
- **実装・運用（ロジック編）**
    - データモデリングとデザイン
    - マスターデータ管理
    - ドキュメントとコンテンツ管理
- **信頼性（安心の実現）**
    - データセキュリティ
    - データ品質
- **信頼性（便利の実現）**
    - データウェアハウジングとビジネスインテリジェンス
    - メタデータ管理
- **全体指針とルール**
    - データガバナンス





## 最後に

以下共にご興味をもたれたら一読をおすすめします。

- [『データマネジメントが30分でわかる本』](https://amzn.to/3fIuty5)
- [Data Platform Guide - 事業を成長させるデータ基盤を作るには #DataEngineeringStudy / 20200715 - Speaker Deck](https://speakerdeck.com/yuzutas0/20200715)
Bytes to Humanreadable Laravel (File Upload Site #1)

今回作ったファイルアプロードのサイトに関して記載して置こうと思います。
Laravelでファイルのサイズを
     $file->getSize();で取るとByteで出てくるためそれをMb, Gb　にする方法です。

1.App に　Helpers フォルダーを作る。
<img width="386" alt="Screen Shot 2020-07-19 at 12.59.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645432/4a7afe75-4bf9-824d-c323-9710d200787b.png">
2. そこにファイルを作る。名前は自由に。
<img width="384" alt="Screen Shot 2020-07-19 at 13.00.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645432/6087c938-58c4-8b20-6136-c58b288ffb0e.png">

3.そのファイルに下記を書きます。

```ruby:SomeClass.php

<?php

namespace App\Helpers;

class SomeClass
{
    public static function bytesToHuman($bytes)
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];

        for ($i = 0; $bytes > 1024; $i++) {
            $bytes /= 1024;
        }

        return round($bytes, 2) . ' ' . $units[$i];
    }
```
4.SomeClass を　app.php の aliases に入れます。
<img width="1099" alt="Screen Shot 2020-07-19 at 13.26.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645432/fe50625d-4186-4ba1-b698-e6cb340d56f4.png">
5.ターミナルで　compose dump-autoload　します. よってrequire（）やinclude（）を必要とせずにPHPクラスを使用できます。
<img width="237" alt="Screen Shot 2020-07-19 at 13.28.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645432/11b581f1-a8a2-b565-17db-e9317f4a1705.png">
6. 最後に view に使えます。
{{ \App\Helpers\SomeClass::bytesToHuman($file->size) }}
<img width="616" alt="Screen Shot 2020-07-19 at 13.29.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645432/7b224d32-249e-89f5-e3c9-fc72d054df60.png">
- 結果
![Screen Shot 2020-07-19 at 13.32.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645432/444d1f3f-462a-a83b-8bd5-60724db31208.png)
から
![Screen Shot 2020-07-19 at 13.33.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645432/ce73b290-54af-b9a5-bf30-d205bcea1ffa.png)
MSFormsのコントロールイベント一覧

#一覧
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637201/6d38fb6f-8223-eed9-d4e6-260950448138.png)

##補足
・WithEvent周りでVBAerを落胆させる`Enter`と`Exit`が際立つ。ご事情ありとは拝察しますが、恨んでます。

・いざ並べてみると、`TextBox`に`_Click`が無いとか、でも`_DropButtonClick`があるとか、その他知らなかったイベントもたくさんで、へー、です。
Data Robot で　壁のひび割れ画像判別やってみた

##Data Robot で　壁のひび割れ画像判別やって見ました
ドローン等で写真をとりその位置画像によるデータ分析を想像しながらやってみました
データ数は事案の関係上約100セットづづに抑えました

![コンクリートの亀裂.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55742/2b6ac5d6-e950-ff9b-6ca1-f5b9a3fb53e4.jpeg)

![コンクリートの亀裂1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55742/66b824f2-a880-e646-605c-6e4e96f9748d.jpeg)
リフトチャート
![コンクリートの亀裂2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55742/ffe2f25d-74c7-cdad-db47-4f08e346bef0.jpeg)
![コンクリートの亀裂3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55742/7cbccafa-2025-6e85-2302-a9ace7c19495.jpeg)
クラス分け
![コンクリートの亀裂4別れています.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55742/e764cf56-df2c-9de3-738c-416aae027d8e.jpeg)
アクティベーションマップ
![コンクリートの亀裂4別れています.JPG2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55742/884940f2-354f-a5e9-1e84-9712ffb91bd0.jpeg)

Elastic-Net Classifier (L2 / Binomial Deviance)　を今回は利用

![コンクリートの亀裂5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55742/3003ade6-0554-ed74-acd6-975c044ff4b6.jpeg)

テストしてみました
![excel.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55742/79d84730-9b63-54b4-fe1a-d389a25152f3.jpeg)

最後までお読みいただきありがとうございます
RailsのViewで共通の部分をページによって表示させたりさせなかったりする。

RailsでView作っているときに、nav-barやside-barは共通部分なので部分テンプレートで書き出してrenderメソッド使うと思いますが、今回トップページにはそれを入れたくないけど、それ以外には全部入れたいみたいな時の対処法です。

#今回の実装に至ったきっかけ
- トップページはオシャレな感じにしたい！上とか横にガチャガチャいらない！
- でも他のページには便利なので入れたい！

ということでトップページ(今回はhomesコントローラーとします)からnav-barとside-barを消す、というか表示させない方法です。

# 使用するコントローラーによって条件分岐する

使用するコントローラー名を取得するメソッドは
**controller.controller_name**
で取得できます。
これによって、条件分岐をapplication.html.erbに書いていきます。

```erb:application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Hoge</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <% if controller.controller_name != 'homes' %>%
      <%= render '/layouts/navbar' %>
      <%= render '/layouts/sidebar' %>
    <% end %>
    <%= yield %>
    <%= render '/layouts/footer' %>
  </body>
</html>
```
#アクション名も取得できる
**controller.action_name**
でアクション名を指定できます。
if controller.action_name=="new"(以下略)
みたいな感じで。

これを使えば同じ画面で登録する、更新する、と言ったボタンのテキストだけを変えることなどもできます。



#参考にした記事
https://qiita.com/lasershow/items/e7a75d3e1653c9ca39d8
【Alpine Linux】AlpineLinuxの基本コマンドメモ

# 公式リファレンス

[Alpine Linux package management](https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management)

# ash

`bash`じゃなくて`ash`

# パッケージマネージャー apk

yumやapt-getのAlpine版

# apk add --no-cache <packages>

Alpineのバージョン3.3以降であれば、 `--no-cache` オプションを使うことで、キャッシュを削除してくれる。

以下の2つは同じ意味

```terminal
$ apk update
$ apk add <packages>
$ rm -rf /var/cache/apk/*

$ apk add --no-cache <packages>
```

# apk add --virtual NAME

パッケージを`NAME`でひとまとめにして管理できる。

```terminal
$ apk add --no-cache --virtual NAME \
  curl... && \
  less...
$ apk del NAME
```

# 参考 

[Alpine Linux で軽量な Docker イメージを作る](Instead of adding all the packages to 'world', create a new virtual package with the listed dependencies and add that to 'world'; the actions of the command are easily reverted by deleting the virtual package)
[Alpine LinuxベースでDockerイメージを作るときのapkのコマンドめも](https://tomcky.hatenadiary.jp/entry/2018/02/20/203657)
ゼロから始めるLeetCode Day91「153. Find Minimum in Rotated Sorted Array」

# 概要

海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

どうやら多くのエンジニアはその対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイトであり、海外のテックカンパニーでのキャリアを積みたい方にとっては避けては通れない道である。

と、仰々しく書いてみましたが、私は今のところそういった面接を受ける予定はありません。

ただ、ITエンジニアとして人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

Python3で解いています。

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day90「1011. Capacity To Ship Packages Within D Days」](https://qiita.com/KueharX/items/3ac6d0260c832d2daf65)

[Twitter](https://twitter.com/kueharx)やってます。

**[技術ブログ](https://kueharx.blogspot.com/)始めました！！**
技術はLeetCode、Django、Nuxt、あたりについて書くと思います。**こちらの方が更新は早いので**、よければブクマよろしくお願いいたします！

# 問題
[153. Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/)
難易度はMedium。
[コーディング面接対策のために解きたいLeetCode 60問](https://1kohei1.com/leetcode/)からの抜粋です。

問題としては、昇順にソートされた配列を，あらかじめ知らないピボットで回転させたとします。（[0,1,2,4,5,6,7]が[4,5,6,7,0,1,2]になるといったような例を思い浮かべていただけると分かりやすいかもしれません。）

そのリストの中から最小の要素を探します。

なお、配列の中に重複した要素はないと考えてよい。

>Example 1:

>Input: [3,4,5,1,2] 
Output: 1

>Example 2:

>Input: [4,5,6,7,0,1,2]
Output: 0

# 解法


```python
class Solution:
    def findMin(self, nums: List[int]) -> int:
        low,high = 0,len(nums)-1
        while low < high:
            mid = (high+low)//2
            if nums[mid] > nums[high]:
                low = mid + 1
            else:
                high = mid
        return nums[low]
# Runtime: 36 ms, faster than 92.74% of Python3 online submissions for Find Minimum in Rotated Sorted Array.
# Memory Usage: 13.9 MB, less than 83.16% of Python3 online submissions for Find Minimum in Rotated Sorted Array.
```

ソートされたリストを順番を保ったまま開始と終点を入れ替えた場合、最も小さい要素を毎回返すようなアルゴリズム、ということですね。
二分探索(O(logn))が適当なアルゴリズムかと思うので、そのまま書いたら良い感じのスピードが出ました。
最近典型的なアルゴリズムの計算量について勉強しなおしているので、できるだけ適当なアルゴリズムを選択できるようになっていきたいです。
数弱なので精進せねば、という感じですね。

それにしてもこの問題二分探索の説明をするには良いですね・・・
線形探索では時間切れになるので、そういったところに目を向けるには非常に良いのでは？
さすがの問題のチョイスだと思いました。


では今回はここまで。
お疲れ様でした。
Twitterにて競艇の３連単予想をつぶやく

#はじめに
ボートレースの３連単予想をここ一ヶ月ほど継続しており、その結果をTwitterに投稿しています。（→[きょう、ていの良い予想は当たるだろうか](https://youhaveniceboat.pythonanywhere.com)）
運営にも慣れてきたし、嬉しいことにフォロワーも少しずつ増えてきたし、徐々に情報発信を増やしていきたい！！
ということで、Twitter（半）自動投稿の仕組みをつくってみました。

#Twitter Developmentにて登録
こちらの記事を参考にさせて頂きました。↓
[Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ　※2019年8月時点の情報](https://qiita.com/kngsym2018/items/2524d21455aac111cdee)

私の場合の違いは、承認まで20日ほどかかった事です..。

==History==
①上記リンクの通りに手続きを済ませたあと、Twitter社から「使用意図などを教えてくれ」とメールが来たので返信。（Web上の申請でも同じ質問を受けたはずなんですけどね..。）
<img width="498" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/daf16714-2977-2977-0dab-025167726923.png">
②３週間近く放置される（涙）
③その後、「すまんな、承認したで」とメールをもらう。~~自分もどうせ即承認されていても手をつけていなかっただろうし、~~ゆとりある心で受け取る。

<img width="526" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/0ba8c8a6-ae5a-5137-79c0-e9f15498f93c.png">

#ということで、つぶやこう！！

```python
import twitter

auth = twitter.OAuth(consumer_key="ここにAPI key",
consumer_secret="ここにAPI Secret",
token="ここにAccess token",
token_secret="ここにAccess token secret")

t = twitter.Twitter(auth=auth)

#予測リストからランダムに１レース選ぶ。
sample = df_pred.sample(n=1).values
text = sample[0][0]+' 第'+sample[0][1]+'の３連単は'+sample[0][2]+'に注目です。'

#ツイート文章作成
status=d_tdy+"の予想を1つ紹介！\n-->"+text+"\n"+\
"その他の情報は以下のサイトから！\n https://youhaveniceboat.pythonanywhere.com\n"+\
" #python #boatrace #自動投稿 #"+sample[0][0]

#投稿する
t.statuses.update(status=status) #Twitterに投稿
```
入力しないといけないAPI keyやAccess tokenなどはTwitter developerのAppsから"Create an app"を押すと、取得できます。
<img width="1100" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/2042ffc3-cbca-4c51-432b-31f3f3a2814d.png">

Keyはこんな感じで確認できます。
<img width="525" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/55f88f49-52eb-70e7-2afe-87e24a6b4055.png">


#できた！！
簡単にできました！これでちょっとだけ時短できそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/403fbef1-89e6-9b2d-7542-4acde4b02af9.png)
Mac上のDockerコンテナでファイル同期が効かない時の対策

# TL;TR
Docer for MacでLinuxなどケース・センシティブなOSをベースにしたコンテナとホストのMacの間でファイル同期をしていると発生するようだ。

解決策としてはMac上にケース・センシティブなボリュームを作成し、それをMacにマウントし、それをコンテナにマウントする。

下記２コマンドで、「あっ」という間にMac上にケース・センシティブなボリュームを作成できる。

```
hdiutil create -type SPARSE -fs hfsx -size 4g -volname linux linux.hfsx.dmg.sparseimage
hdiutil attach -nobrowse -mountpoint linux linux.hfsx.dmg.sparseimage
```

# 背景と問題
エンジニアチーム内や本番・テストなど異なる環境でも、OSやミドルウェアやそれらのバージョンなどを極力同じにするという目的で、うちではDockerコンテナでMac上にローカル開発環境を構築している。新しいメンバーが入っても、コンテナを起動するだけで開発環境の構築ができる。

Mac上のソースコードがあるディレクトリをDockerコンテナ内のWebサーバのドキュメントルートにマウントすれば、ローカルで編集したものがすぐにローカルWebサーバに反映される。・・・はずだったのだが、まぁまぁ頻繁に変更が反映されないことがある。
コンテナをrestartすると反映されるので、発生した場合はそうしていたが、いい加減効率が悪いので直したかった。

変更が反映されていないときにコンテナ内でのファイルを確認すると、変更は反映されている。しかし、ブラウザで見ると反映されていない。

そして、たまたまエラーになっていた時にそのファイル名を見ると、FooBar.php であるはずのファイル名が foobar.php とログには出ている。しかし、コンテナ内をlsコマンドで確認するとFooBar.phpはあってもfoobar.phpは無い。

試しにfoobar.phpをvimで開くと、なんと開けるうえに内容が古いものになっている。そして、FooBar.phpを開くと新しいものになっている。
しかし、やはりfoobar.phpはlsでは出てこない。

# 原因
コンテナがベースにしているOSがケース・センシティブだが、コンテナ内で使用しているファイルシステム自体はMacのを継承してケース・インセンシティブなのが問題なようだ。コンテナ内のOSはファイル名の大文字小文字を区別する前提で動いているが、使用しているファイルシステムは大文字小文字を区別しない、ということで、Macとコンテナの間でファイルを同期する際にどこかで不整合が発生しているらしい。

発生するときとしない時があったのは、全て小文字のファイル名だと問題にならなかったということだ。

# 解決策
### ケース・センシティブなボリュームを作成する

参考：https://github.com/docker/for-mac/issues/320#issuecomment-315324629

Mac上にケース・センシティブなボリュームを作成し、それをMacにマウントし、それをコンテナにマウントする。

まず、ケース・センシティブなボリュームを作成する。パーティションサイズを変えたりフォーマットしたりと面倒なことは一切ない。下記コマンドで一瞬で4GBのケース・センシティブなボリュームが作成できる。

```shell
hdiutil create -type SPARSE -fs hfsx -size 4g -volname linux linux.hfsx.dmg.sparseimage
```

そしてこれを下記コマンドでMacにマウントして使えるようにする。マウントする場所は `-mountpoint` で指定している。

```shell
hdiutil attach -nobrowse -mountpoint /Users/hoge/linux linux.hfsx.dmg.sparseimage
```

マウントしたら普通のディレクトリと同じように使用できる。

<img width="267" alt="Screen_Shot_2020-07-19_at_11_04_45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138322/613dc4cf-b26b-07ec-b692-5c60213fa6c8.png">


ここをコンテナのvolumeとしてマウントすれば、コンテナ内のケース・センシティビティと一致して問題が発生しないはず。
例えばdocker-composeならばこんな感じに。

```yaml
services:
  ctober-web-server:
    ...
    volumes:
      - /Users/hoge/linux:/var/www/html:cached
```

### 不要になったら

このボリュームが不要になったら下記でunmountできる。

```shell
hdiutil eject linux
```

また、Macを再起動したらまたマウントする必要がある。その時は上記の `hdiutil attach` コマンドを実行すれば良い。

### ボリュームのサイズを変更する

ディスクイメージの作成後にサイズを大きくしたい場合など、 `hdiutil resize` を使用してサイズを変更できる。（自分の場合は、実行は一瞬でなんの画面表示もなかったがボリュームサイズを見てみると変更されていた。）

```shell
hdiutil resize -size 8G linux.hfsx.dmg.sparseimage
```

# IDEでの警告
JetBrainsのPhpStormなど使用していると、作成したケース・センシティブなボリュームにあるファイルを編集すると、IDEが認識しているケース・センシティビティとファイルシステムのが違うよ、と警告が表示される。
そんなときは、Help -> Edit Custom Properties でファイルに下記を追加する。

```
idea.case.sensitive.fs=true
```

そして、IDEをリスタートすれば適用される。
参考：https://confluence.jetbrains.com/display/IDEADEV/Filesystem+Case-Sensitivity+Mismatch
ホストOSがLinuxのときにカーネルのバージョンを上げたらVirtualBoxの仮想環境立ち上げでエラーが出たので備忘録


# RyzenCPUが入ったLinuxでVirtualboxに仮想環境を起動したらエラーが出たので忘備録
## 前提
環境 Linux Mint Debian Edition 4 Ryzen3500U
インストール時にカーネルのバージョンを上げています

```shell:
$ uname -a
Linux PC名 5.6.0-0.bpo.2-amd64 #1 SMP Debian 5.6.14-2~bpo10+1 (2020-06-09) x86_64 GNU/Linux
```
インポートしようとすると
こんな感じのエラーを吐いて怒られる
![Virtualbox_error![Virtualbox_error1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482573/8271e87a-f840-bfa9-e089-b3fe6af57d82.png)
1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482573/9c545901-6695-93d4-28f5-0729b47f6b02.png)
![Virtualbox_error2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482573/202bb8bb-98c6-03b2-1e99-2dcd9fcd8cc7.png)

>終了コード : NS_ERROR_FAILURE (0x80004005)
コンポーネント: MachineWrap
インターフェース: IMachine {85632c68-b5bb-4316-a900-5eb28d3413df}


## 解決方法
とりあえず


```shell:手順1
$ sudo /sbin/vboxconfig 
vboxdrv.sh: Stopping VirtualBox services.
vboxdrv.sh: Starting VirtualBox services.
vboxdrv.sh: Building VirtualBox kernel modules.
This system is currently not set up to build kernel modules.
Please install the Linux kernel "header" files matching the current kernel
for adding new hardware support to the system.
The distribution packages containing the headers are probably:
    linux-headers-amd64 linux-headers-5.6.0-0.bpo.2-amd64
This system is currently not set up to build kernel modules.
Please install the Linux kernel "header" files matching the current kernel
for adding new hardware support to the system.
The distribution packages containing the headers are probably:
    linux-headers-amd64 linux-headers-5.6.0-0.bpo.2-amd64

There were problems setting up VirtualBox.  To re-start the set-up process, run
  /sbin/vboxconfig
as root.  If your system is using EFI Secure Boot you may need to sign the
kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load
them. Please see your Linux system's documentation for more information.
```

カーネルのヘッダファイルがないと怒られるてるのでヘッダをインストール

```shell:手順2
$ sudo apt install -y linux-headers-amd64 linux-headers-5.6.0-0.bpo.2-amd64
```

その後

```shell:手順3
$ sudo /sbin/vboxconfig 
vboxdrv.sh: Stopping VirtualBox services.
vboxdrv.sh: Starting VirtualBox services.
vboxdrv.sh: Building VirtualBox kernel modules.
```

でめでたく起動
おしまい
Vue.js  メソッドと算出プロパティの違い　考察１

#メソッド(methds)とプロパティ(coomputed)の比較

二つのコードを例に考察

```javascript

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Vueの練習 28p~</h1>

    <!-- テンプレートが読みにくい例 -->
<div id="app">
<p>{{mail.split('@')[0].toLowerCase()}}</p>
</div>

<!-- 算出プロパティで読みやすくした例 -->
<div id="app2">
<p>{{email}}</p>
</div>

<!-- メソッドで記述した例 -->
<div id="app3">
<p>{{email2()}}</p>
</div>



<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>

//テンプレートが読みにくい例
new Vue({
    el:'#app',
    data:{
        mail:'TEST@tes.jp'
    }
})

//算出プロパティで読みやすくした例
new Vue({
    el:'#app2',
    data:{
        mail2:'TEST@tes.jp'
    },
    //演算した結果を取得する算出プロパティ
    computed:{
        email: function(){
          return this.mail2.split('@')[0].toLowerCase();
        }
    }
})

 //メソッドで表した例
new Vue({
    el:'#app3',
    data:{
        mail3:'TEST@tes.jp'
    },
    methods:{
        email2:function(){
           return this.mail3.split('@')[0].toLowerCase();
        }
    }
})   



</script>
</body>
</html>
```

結果
![スクリーンショット 2020-07-18 7.35.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670884/c76377f5-1d5f-8a73-0cb9-d3556a3abbe8.png)

上記コードでは大文字で書いた

```
TEST@tes.jp
```
の部分を小文字に変えて表示するということを実行する際、
①マスタッシュに記載
②算出プロパティを使用
③メソッドを使用

で書き分けている。
**これを見るだけだと②と③の違いが分からない。**


次のコードサンプル

```js
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Vueの練習 31p-</h1>

<div id="app">
    <form>
        <input type="button" value='クリック' v-on:click='clickfunc'>
    </form>

<div>算出プロパティ:{{randomc}}</div>
<div>メソッド:{{randomm()}}</div>
<div>現在日時:{{current}}</div>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>

new Vue ({
    el:'#app',
    data:{
        current: new Date().toLocaleString()
    },
    computed: {
        //算出プロパティ経由で乱数を取得
        randomc:function(){
            return Math.random();
        }
    },
    methods: {
        //クリック時に処理を実行
        clickfunc: function(){
            this.current = new Date().toLocaleString();
        },
        //メソッド経由で乱数を取得
        randomm:function(){
            return Math.random();
        }
    },
})

    
</script>
</body>
</html>
```

結果
![スクリーンショット 2020-07-18 7.38.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670884/8c8c036b-9ad0-52a3-811c-9ca52731cd87.png)

ボタンをサイドクリックすると
![スクリーンショット 2020-07-18 7.41.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670884/501657e7-00e1-4a05-a566-9e4faf3aa10e.png)

**メソッドの値と、現在時刻が変化（算出プロパティの値は変わらない）**

##ポイント
メソッドはボタンクリックの際、再描画される（乱数を再取得）。算出プロパティでは再取得されない。
算出プロパティではそれが依存するプロパティ（this.~）で表される値が変更された場合にのみ評価される。

→この場合メソッドと算出プロパティの違いが具体的にどうなのか、そこの理解がやはりまだ足りない。

算出プロパティがメソッドのように再描画されない点にポイントがあるということがまずわかった。
そこが本日の学び（2020/7/19)

続きます
【俺は】OSSの未来を考える【コードチューバーになる】

## 野生のハンバーグは海を泳いでるんだぜ

先日、GitHubの全パブリックリポジトリを北極圏の地下に
1000年間保存するプロジェクトが実施されたようです。

[GitHubの全パブリックリポジトリを北極圏の地下に1000年間保存する](https://cloud.watch.impress.co.jp/docs/event/1219094.html)

### Arctic Code Vault Contributor
![git.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533968/bd17ab30-dfb3-5bef-fd99-d6899f1ebcd6.png)

[The GitHub Blog](https://github.blog/2020-07-16-github-archive-program-the-journey-of-the-worlds-open-source-code-to-the-arctic/)

オープンソースは人類の共有財産であるとして、
万が一世界的な規模での災害などがあった場合でも、
オープンソースのコードを次世代の人類に
確実に残していくことを目的としています。

[Publickey](https://www.publickey1.jp/blog/20/1000github_archive_program.html)

![macros.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533968/bdc59640-3b43-513e-36ae-65b9dad541b8.png)
この1000年前の古代人類文明の記録は、何の特別でもなく当時のありふれた女の子の練習コードのひとつに過ぎなかった。
それはこの古代文明社会がどれほど優れていたかを示すだろう。

### 私のリポジトリも無事保存されプログラマ冥利に尽きるというものです。

特に選ばれた人が保存された訳ではなく、
アクティブなパブリックリポジトリは全て保存されたようなので
イキリ散らす訳でもなく

プログラマ民にとっての祝祭日になったと思います。

最高の名誉であり
この時代の全てのOSSコントリビューターへの感謝と敬意とご褒美です。

さて、しかし
ただの名誉でおまんまは喰えないのだよという民の声も正しく

現在の世界の英知のGitHubがスナップショットされたことで、
OSSは新ステージへ進んでも良い気がします。

YouTubeが世界を変えたように、プログラムが世界を変える。

## CodeTube
![codetube.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533968/811987ed-8040-2d44-c347-3697cacc782b.png)

創設を提言したいと思います。
某マイクロソフトさんはIoT未来を考えているようですし
カスタムIoTモジュールのOSS商用プラットホームでどうでしょう。

OSSにどうやって報酬を還元するかというのが最大の難所ですが

CodeTubeとIoTインストーラをリンクさせて、
CodeTubeからしかDLできないようにするとか。

CodeTube上で丸パクリOSSの氾濫をどう防ぐかは、
委員会とユーザ投票で商用を認めるか決めるとか。
社会の役に立つかは市場が決める方針です。

プログラマが世界を変える。
そんな未来に期待したいですね。
configure_permitted_parametersメソッドについて

## devise gemで追加したいカラムを設定する方法。

まず結論から言ってしまうと`devise gemをインストールしたら新規登録などに関わるストロングパラメーターを編集することはできません。`
つまりdeviseで保存を許可されているのはマイグレーションファイル生成時に記述されているカラムのみになるのです。

新規登録時にニックネーム情報も保存できる様になりたい。。。


そこで使用するのが devise gemインストール後使用できる<font color="red">configure_permitted_parametersメソッド</font>です。

記入例
***

```ruby
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  private
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
  end
end
```

アプリケーションコントローラーで上記の様に新規登録でニックネームを許可することにより<br>パラメーターを受け取ることができます。

*permit*後の書き方は`(:アクション, キー: [:追加したいカラム])`となります。
ログイン画面作成（備忘録）　section70

①まずは、必須項目のチェック（しっかりを記述されているか確認）
index.phpの<form action="" method="post" enctype="multipart/form-data">

actionが空欄の場合、自分自身にファイルが返る仕組み
ここで自分自身のファイルに返してエラーのチェックをする
エラーチェックが正常に通過すればcheck.phpに遷移するするようにするのでactionは空欄のままで良い
index.phpの中でエラーチェックを行う（ファイルの先頭にエラーチェックプログラムを記述していく）

ニックネームが空であるかどうかチェックするプログラム

```
<?php
if($_POST['name'] === ''){
	$error['name'] = 'blank';
}
?>
```
＞＞入力欄のnameが空だったら、メッセージ表示する

このままだとフォーム外でエラーが発生するので変数に格納してエラー表示したい場所に
変数を持っていく。

$error['name'] = 'blank';
→名前が入力されていない状況（blankとする）を配列$error['name']に入れておく。

```
<?php if($error['name'] === 'blank'): ?>
<p class=error>※ニックネームが未入力です</p>
<?php endif; ?>
```
＞＞上記のコードをエラの表示させたい場所に記述する。
【AzureAD】ネストグループだと色々不具合がある件

※この記事は3分くらいで読めます

AzureADで以下を検討している方にお勧めの情報です。
※ユーザプロビジョニング
※エンプラアプリとのシングルサインオン
※グループ単位のライセンスの割り当て


先日MSサイトで以下の記事を見つけました。
https://docs.microsoft.com/ja-jp/azure/active-directory/users-groups-roles/directory-service-limits-restrictions

※一部抜粋

次のシナリオでは、入れ子になったグループはサポートされません。
★アプリ ロールの割り当て (アプリへのグループの割り当てはサポートされていますが、直接割り当てられたグループ内で入れ子になっているグループにはアクセス権はありません)。アクセス権とプロビジョニングの両方
グループベースのライセンス (グループのすべてのメンバーにライセンスを自動的に割り当てます)
Office 365 グループ。

・ユーザプロビジョニング
・エンプラアプリのシングルサインオン
・ネストグループのライセンス割り当て
はネストグループだとサポートされていないようです。

まじかよ。。。

実際に本当にそうなるか試してみます
ここではeigyo_allのグループを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/314873a6-284a-8731-70f1-43609e126624.png)

eigyo_allの配下にeigyo_GPを追加します。
eigyo_GPの配下にはtestuserが格納してあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/958b62af-2f9e-2dac-8c88-fd582dc55178.png)

salesforceのユーザとグループにeigyo_allを割り当てます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/ce10ea1f-84d4-53d2-12fd-d420ea0dde27.png)

testuserで認証テストしてみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/fe1de7ca-3f0b-0661-eb22-6c3675e1b323.png)

ロールが割り当てられていないとエラーが出ました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/81976953-aa6a-51a1-e5eb-e75a4a78c5be.png)

ADの世界ではネストグループは当たり前のように使用されているので
それがAzureADで使えないとなるとこれは痛いです。是非改修してほしい。

プロビジョニングで、徐々にグループ追加するパターンの場合
大元のSGを作成し、そこに差分SGを追加していくって事は出来なくなります。
ADのSG情報がそのまま利用できないのはつらいですね。

ご参考になればと存じます。
〔JavaScript〕配列のコピーの仕方

#はじめに
配列のコピーは`const newArr = arr;`と文字列と同じようにコピーしようとすると片方が更新された時にもう一方も変更がかかってしまいます。
知らなくて躓いてしまったので配列のコピーを備忘録として残しておきます。


##何故できないのか
`JavaScript`では、配列は<font color="Tomato">**オブジェクトの一つ**</font>であり、<font color="Tomato">オブジェクトは**参照の値渡し**になるため、配列も参照渡し</font>になります。
なので、変数にはオブジェクトの参照が格納されています。

```javascript
const arr1 = [0, 1, 2];

// arr2にarr1に入っている参照を代入
const arr2 = arr1;
console.log(arr2); 

//出力結果
//[0, 1, 2]

// arr2を変更
arr2[1] = 10;

// arr1でも変更される
console.log(arr1[1]); 

////出力結果　
//10
```
元の配列を参照しているだけなので、<font color="Tomato">**どちらかの値を変更するともう一方の配列の値も変わってしまう**</font>という事象が起こります。
そのため配列をコピーして新しく配列を作る場合には一工夫する必要があります。

#コピーの仕方
##concat
```javascript

const newArr = [].concat(arr);
```
**空の配列**に**元となる配列**を繋げることで、配列をコピーし新しい配列を作っています。

##slice
```javascript
const newArr = arr.slice(0, arr.length);
```
コピーしたい配列から、スライスで初めから終わりまで**値を切り取って**新しい配列に格納することによってコピーしたい配列をコピーした新しい配列が作られます。

#スプレッド構文
```javascript
const newArr = [...arr];
```
角括弧の中で...の後にコピーしたい配列名を入れるとその配列をコピーした新しい配列を作成することができます。

#Array.from
```javascript
const newArr = Array.from(arr);
```
配列のオブジェクトや反復可能オブジェクトから、シャローコピーの `Array`インスタンスを生成します。

#map
```javascript

const newArr = arr.map( x => x );
```
配列から各要素に処理を加えて新しい配列を作ることができます。
何も処理を加えなかった場合はオリジナルの配列をそのままコピーした配列を作れますが、処理速度が速くないので<font color="Tomato">**配列をコピーしたいだけの場合**はあまり**おすすめではない**</font>です。

#ディープコピー
###二重配列の場合
上記の方法で二重配列のコピーでできなかったので調べてみました。

```javascript

const newArr = JSON.parse(JSON.stringify(arr));
```
JSON.parse()メソッドは文字列を JSON として解析し、文字列によって記述されている JavaScript の値やオブジェクトを構築します。

#参考リンク
[Javascriptの配列をコピーする方法の処理速度を比べてみた](https://yukimonkey.com/site-speed/array-copy/'Javascriptの配列をコピーする方法の処理速度を比べてみた')
競技プログラミング練習記 No.48【ABC114練習】

初回 -> [はじめに](https://qiita.com/easychoco/items/a9ae28aca97cfe47091f)

[ABC114](https://atcoder.jp/contests/abc114)を解きました。
3完です！
D問題は解説を見て解きました。

|問題|時間|アルゴリズム|実行時間
|:-:|:-:|:-:|:-:|
| A |  1min |-| 6ms|
| B |  4min |-| 8ms|
| C | 60min |深さ優先探索| 8ms|
| D | - |素因数分解| 7ms|


# まとめ
先にまとめを載せます。これ自体は最後に書いてます。


ある数字の約数の個数は、素因数分解したときの指数で決まります。

C問題はもっと早く解きたかったし、D問題も解けそうだった。
つぎは解けるように復習します。。。

## A - 	753

```c++
  int x;
  cin >> x;
  if (x == 3 || x == 5 || x == 7) cout << "YES";
  else cout << "NO";
```
入力が`3`か`5`か`7`の時に"YES"と出力します。

## B - 754

``` c++
  ll s;
  cin >> s;
  ll ans = s;
  while(s >= 100)
  {
    ans = min(ans, abs((s % 1000) - 753));
    s /= 10;
  }
  cout << ans;
```
問題文には「文字列」とありますが、数値として受け取りました。
そうすると、`%1000`の演算で下3桁を取り出せますね。
10で割って下三桁を取り出すことを繰り返しました。

## C - 755

``` c++
ll n;
ll ans = 0;

bool check357(ll num)
{
  bool ret3 = false;
  bool ret5 = false;
  bool ret7 = false;
  while(num > 0)
  {
    int res = num % 10;
    ret3 |= (res == 3);
    ret5 |= (res == 5);
    ret7 |= (res == 7);
    num /= 10;
  }
  return (ret3 & ret5 & ret7);
}

void dfs(ll num, ll digit)
{
  if (num > n) return;
  if (num > 100) ans += check357(num);

  dfs(num + digit * 3, digit * 10);
  dfs(num + digit * 5, digit * 10);
  dfs(num + digit * 7, digit * 10);
}

void solve()
{
  cin >> n;
  dfs(0, 1);
  cout << ans;
}
```

[ABC119のC問題](https://atcoder.jp/contests/abc119/tasks/abc119_c)の「解説にある解法」と似た解き方です。
（私がABC119を解いたときとは違う解法です。）

DFSで`3,5,7`を使った数字を作り、条件を満たすものであれば答えとしてカウントします。
最大9桁であることから`3^9`通りの数字ができますが、計算量が間に合うためこの解き方をしました。
解くのに時間がかかってしまったので反省。。。

## D - 756

``` c++
  int n;
  cin >> n;
  if (n < 10) 
  {
    cout << 0;
    return;
  }

  map<int, int> primes;
  for(int i = 1; i <= n; ++i)
  {
    int n = i;
    for(int p = 2; p <= i; ++p)
    {
      while(n % p == 0)
      {
        primes[p]++;
        n /= p;
      }
    }
  }

  int ans = 0;
  int over74 = 0;
  int over24 = 0;
  int over14 = 0;
  int over4 = 0;
  int over2 = 0;
  for(const auto& p : primes)
  {
    if (p.second >= 74) over74++;
    if (p.second >= 24) over24++;
    if (p.second >= 14) over14++;
    if (p.second >=  4) over4++;
    if (p.second >=  2) over2++;
  }

  ans += over74;
  ans += over24 * (over2 - 1);
  ans += over14 * (over4 - 1);
  ans += over4 * (over4 - 1) * (over2 - 2) / 2;
  cout << ans;
```

ある数字の約数の個数は、素因数分解したときの指数で決まりますね。
ある数`N`を素因数分解すると`N = 2^a * 3^b * 5^c * ...`となります。
このとき、約数の個数は`(a + 1) * (b + 1) * (c + 1) * ...`個になります。

例えば`N = 105`の時は`35 = 2^0 * 3^2 * 5^1 * ...`より、
`(0 + 1) * (2 + 1) * (1 + 1) = 6個`の約数があります。
`a,b,c,...`が`0`でも成り立つのでよくできてますね。

今回は約数の個数が75になる数字を求めるので、
`(a + 1) * (b + 1) * (c + 1) * ...  = 75`
となる数字を探します。

`75 = 3^1 * 5^2`なので、
`3 * 5 * 5 = 75`
`3 * 25 = 75`
`5 * 15 = 75`
`1 * 75 = 75`
ですね。

約数の個数の式と見比べて、
N!を素因数分解したときに指数が`74,24,14,4,2`となる素因数を探します。
指数はぴったり`74`でなくても、`74`以上なら対象になります。
もちろん、`74`以外の`24,14,4,2`もそれ以上なら対象です。

ここまでわかれば、組み合わせの数を足して答えになります。


以上です。ありがとうございました。
matplotlibで簡単にグラフを書く

あれ、あのグラフってどんな感じだったっけ？というときにさらっと書いて確認したい（のでWarningとかが出ても気にしない）。

## Log
```
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 10, 0.01)
y = np.log(x)

plt.grid()
plt.plot(x,y)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120864/6b181cbf-776a-a57b-4269-abe1196a36b4.png)



## Sigmoid
```
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-10, 10, 0.01)
y = 1 / (1 + np.exp(-x))

plt.grid()
plt.plot(x,y)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120864/e8deeff9-7cd6-06a1-81d0-af1344dfff34.png)


##tanh
```
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-10, 10, 0.01)
y = (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))

plt.grid()
plt.plot(x,y)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120864/c72f7299-89d3-75a3-f173-60ea830a0b51.png)


##Relu
```
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-10, 10, 0.01)
y = np.maximum(0, x)

plt.grid()
plt.plot(x,y)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120864/e7f0b39c-8b38-489e-0caf-ab0e0985a0f5.png)
Next.jsでimportのaliasを貼るのに割とハマった話

Next.jsでimportのaliasを貼る時に、自分がハマったのでその時に解決した方法を解説していきます。
手順だけ知りたい人は[手順](#手順)から読んでください。

この記事で解説する手順はTypeScriptを利用している時に綺麗にできる方法です。
TypeScriptなんて使ってないぞと言う人は下の背景と[まとめ](#まとめ)だけ読んでいただければいい方法が見つかるかもしれません。

## 背景

TypeScriptを導入したプロジェクトでは`~`に`src`ディレクトリなどのaliasを貼るのにいろいろな場所にコンフィグを書かなければいけません。

多くの記事で紹介されているのは`tsconfig.json`と`webpack.config.js`に設定を記述して[eslint-import-resolver-webpack](https://www.npmjs.com/package/eslint-import-resolver-webpack)を使って解決する方法です。

それぞれのファイルでは以下のように記述します。

```json:tsconfig.json
{
  "compilerOptions": {
    ...
    "baseUrl": "./",
    "paths": {
      "~/*": ["./src/*"]
    },
    ...
  }
}
```

```js:webpack.config.js
const path = require('path');

module.exports = {
  // ...
  resolve: {
    alias: {
      '~': path.resolve(__dirname, './src'),
    },
    extensions: ['.ts', '.tsx', '.js', '.jsx'],
  }
  // ...
};
```

```js:.eslintrc.js
const path = require('path');

module.exports = {
  // ...
  settings: {
    'import/resolver': {
      webpack: {
        config: path.resolve(__dirname, './webpack.config.js')
      },
    },
  },
  // ...
};

```

しかし[このissue](https://github.com/benmosher/eslint-plugin-import/issues/1286)で議論されているように、Next.jsは`webpack.config.js`を読み込まないため、この方法を使うことができません。

[このコメント](https://github.com/benmosher/eslint-plugin-import/issues/1286#issuecomment-468342946)で書かれているように設定することでaliasを貼ることができますが、本来不要な`webpack.config.js`と`alias-config.js`を書かないといけなくなり、あまりスマートじゃありません。

もし、Next.jsのプロジェクトにTypeScriptを使っている場合、[eslint-import-resolver-typescript](https://www.npmjs.com/package/eslint-import-resolver-typescript)を使うことで簡単に解決できます。

## 手順

まず、必要なパッケージを追加します。

```shell
# npm 
npm i -D eslint-plugin-import @typescript-eslint/parser eslint-import-resolver-typescript
 
# yarn 
yarn add -D eslint-plugin-import @typescript-eslint/parser eslint-import-resolver-typescript
```

あとは、必要なコンフィグを書いていきます。

```json:tsconfig.json
{
  "compilerOptions": {
    ...
    "baseUrl": "./",
    "paths": {
      "~/*": ["src/*"]
    },
    ...
  }
}
```

```js:next.config.js
const path = require('path');

module.exports = {
  // ...
  webpack(config) {
    config.resolve.alias = {
      '~': path.resolve(__dirname, './src/'),
    };
    return config;
  },
  // ...
};
```

```js:.eslintrc.js
const path = require('path');

module.exports = {
  // ...
  plugins: [
    // ...
    'import'
  ],
  settings: {
    'import/resolver': {
      typescript: {
        config: path.join(__dirname, './webpack.config.js'),
        alwaysTryTypes: true
      },
    },
  },
  // ...
};

```

ここまでできれば、プロジェクトの中で`~/hoge`でimportできるはずです。

## まとめ

最後まで読んでいただきありがとうございました。

今回はTypeScriptを使っていることを前提に話していきましたが、TypeScriptを導入していない場合は[このコメント](https://github.com/benmosher/eslint-plugin-import/issues/1286#issuecomment-468342946)で書かれている通りに記述するのが一番綺麗にできると思います。
どうしてもファイルを増やしたくない場合は[eslint-import-resolver-alias](https://www.npmjs.com/package/eslint-import-resolver-alias)を使うのも一つの方法です。

他にいい方法があれば、是非コメントで教えてください！

## 参考
- https://www.npmjs.com/package/eslint-import-resolver-typescript
- https://github.com/benmosher/eslint-plugin-import/issues/1286