OmniAICreator/Qiita-1.07M huggingface dataset:
Gitの基本概念〜用語説明(リポジトリなど）〜

#はじめに
本記事ではGitの基本概念。具体的には、リポジトリ、コミット、ワークツリー、インデックスについて説明していきます。
※投稿について間違った説明、解釈をしている場合はぜひコメントお願い致します。

#そもそもGit(ギット）とは？
結論、Gitとは、ファイルの変更履歴を記録、追跡するためのバージョン管理システムです。
Gitは、「いつ、誰が、どのファイルのどの箇所を、どんなメッセージを残して変更したか」をファイルの変更履歴として残してくれます。Gitのおかげで、共同開発やファイルの変更履歴の記録などをより簡単にこなすことができるようになりました。

#リポジトリ
バージョン管理を行うには、バージョンの保存場所が必要です。
その保存先のことを”リポジトリ”と言います。リポジトリという箱の中にバージョン情報（ファイルの変更履歴）の１つ１つが保管されているイメージです。

#コミット
先ほどリポリトリは箱だ。と説明しましたが、コミットは箱の中身です。
”コミット”は1つ1つのバージョンのことを指します。また、コミットを作成することを”コミットする”と言います。
今回詳しい説明は省きますが、1つ1つのコミットには様々な情報が入っています。
主な６つを紹介します。
・リビジョン番号
・コミットした人
・コミットした日時
・コミットしたときのファイル内容の差分
・コミットメッセージ
・親コミット（1つ前のコミット）のリビジョン番号

#ワークツリーとインデックス
”ワークツリー”は,Gitでバージョン管理されているフォルダの中身を指します。
はじめに、ファイルに変更が加えられるとまずはワークツリーに変更が反映されます。この段階では、前回のコミットされたフォルダと比較して、前回との変更箇所がわかるだけです。
次に、ワークツリーから次のコミットに含めたいファイルの変更箇所を選択します。このことを”ステージする”と言います。
そして、ステージされたファイルの変更箇所は”インデックス”に反映されます。
最後にインデックスへステージされた変更箇所のみをコミットします。
”インデッックス”はファイルの変更からコミットまでの中間地点的な役割を果たしています。
ではなぜ、インデックスが必要になるのかと言うと、インデックスはコミットを行う前に、ワークツリーの変更箇所の中から関連性のある変更のまとまりを選択してくれるからです。
OpenCVによるごく単純な間違い探し

　知り合いが画像の差分を見比べるプログラムが必要だといっていたのでPythonとOpenCVで組んでみた。要はOpenCVを用いた間違い探しだが、**画像同士でいっさいのズレがないことが条件となる**ので、実務的なアレには向かないかもしれない。よりロバストな間違い探しが必要な方は[この記事](https://qiita.com/ika_kk/items/32c4986825c86ad92f36)などを参考にした方がいいかも。実装はこの記事の方法のが10倍ぐらい軽いと思うけど……。

#結果

　以下のような画像が出力される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/05488c6f-49a5-f36d-ad8c-780a1b6ae49e.png)
（画像は[Wikipedia](https://ja.wikipedia.org/wiki/%E9%96%93%E9%81%95%E3%81%84%E6%8E%A2%E3%81%97)より引用）

# ソースコード

```python
import cv2
import matplotlib.pyplot as plt

img1 = cv2.imread('img1.png')
img1 = cv2.cvtColor(img1,cv2.COLOR_BGR2RGB)
img1 = img1/255
img2 = cv2.imread('img2.png')
img2 = cv2.cvtColor(img2,cv2.COLOR_BGR2RGB)
img2 = img2/255
dif = cv2.absdiff(img1,img2)
dif[dif>0] = 1

fig,axs = plt.subplots(2,2)
ar = axs.ravel()
ar[0].imshow(img1)
ar[1].imshow(img2)
ar[2].imshow(img1*dif*0.8 + img1*0.2)
ar[3].imshow(img2*dif*0.8 + img2*0.2)
plt.show()
```

　本質的な処理はOpenCVによる数行で済むが、matplotlibで表示するための下処理でけっこう行数がかかっている。要は`cv2.absdiff`で差分画像がとれるので、それをマスクとして利用している。diffそのままだとRGBチャンネルそれぞれに対して差分を取っているので、`dif[dif>0] = 1`という操作によりマスクにする。

　思ったよりも手間取った点としては、OpenCVの画像データは`int`型と`float`型の両方とも取れるようになっており、普段は便利なのだが今回はそのせいでマスクが上手くいかなかった。結果、画像を読み込んだ時点で`/255`して強制的に`float`にキャストしている。
【自分用メモ】Win10のOpensshにてBad owner or permissions on ~/.ssh/config

自分用メモ

#環境
windows10 2004 x64 home

#事象発生
タイトル通り(Bad owner or permissions on ~/.ssh/config)エラー発生

#対策
コンピューター名とユーザー名を同じにしない

#やってはいけないこと
ファイルや.sshフォルダーのセキュリティやパーミッションを変えてはいけない。

取り急ぎ。
11. 【Android/Kotlin】Toast

#はじめに
DreamHanksのMOONです。

前回はライブラリを追加する方法について説明しました。
[10. 【Android/Kotlin】ライブラリを追加](https://qiita.com/DreamHanks/items/b0326a6ede9c801a7137)

今回は`Toast`という通知メッセージについて説明していきます。

#Toastとは
Toastはみんなさんが考えている`トーストパン`の意味と同じです。
トースト機器でトーストが完成すると飛び出るようなものだという意味で、
通知メッセージが画面に現れることを意味します。

今回はこのテキストを入力し、Toastメッセージにテキストを表示していきます。

#Toast追加

・Activityを作成

```kotlin:ToastActivity.kt
package com.example.practiceapplication

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.*

class ToastActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_toast)

        val text_et = findViewById<EditText>(R.id.text_et)              //EditText（入力エリア）
        val toast_btn = findViewById<Button>(R.id.toast_btn)            //追加ンボタン

        //ボタンのクリックイベントを設定
        toast_btn.setOnClickListener {
            //入力したテキストに対するToastメッセージを生成
            Toast.makeText(applicationContext, text_et.text.toString(), Toast.LENGTH_SHORT).show()
        }

    }

}
```

ボタンクリックイベント内にToastを生成するためのコードを追加します。


・レイアウトのxmlファイルを作成
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/ed92e7e3-bf92-4f43-0165-9be0ba0437a4.png)

```xml:activiy_toast.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ToastActivity"
    android:gravity="center">

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/text_et"
        android:inputType="text"
        android:hint="テキストを入力してください。"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/toast_btn"
        android:text="ボタン"/>

</LinearLayout>
```

#アプリ起動
・`こんにちは`というテキストを入力し、ボタンをクリックした場合
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/05b7bb68-ebd0-141e-6294-b5315823f1b2.jpeg" width=50%>

・`DreamHanks`というテキストを入力し、ボタンをクリックした場合
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/1d7b6a94-37f8-8cad-0808-a926b68e0ecf.jpeg" width=50%>

#終わりに
今回は`Toast`という通知メッセージについて説明しました。

次回はCircleImageViewという外部ライブラリを使用してみます。
[12. 【Android/Kotlin】丸いイメージ（CircleImageView）](https://qiita.com/DreamHanks/items/b57d9eb22d70f70c0231)

最新内容については下記のリンク（DreamHanksのブログ）で確認することができます。
[DreamHanksブログ（Android/Kotlinアプリ開発）](http://blog.dreamhanks.com/android-kotlin%e3%82%a2%e3%83%97%e3%83%aa%e9%96%8b%e7%99%ba/)
【NestJS】ヘルスチェック（v7版）

[【NestJS】ヘルスチェック（v6版）](https://qiita.com/piggydev/items/922be61c323e047a90c1) を NestJS 7 へのバージョンアップに伴い、変更した内容になります。

# 環境

- [NestJS 7.6.5](https://nestjs.com/)
- [TypeORM 0.2.31](https://github.com/typeorm/typeorm)
- [@nestjs/terminus 7.1.0](https://github.com/nestjs/terminus)

NestJS 6 時代は、`godaddy/terminus` が必要でしたが、7 から依存が排除されています。

# インストール

```
yarn add @nestjs/terminus --no-optional

// or

npm install --save @nestjs/terminus --no-optional
```

# 実装

- ほとんど、↓のページに書いている通りです。
  - https://docs.nestjs.com/migration-guide#terminus
- `const dbConfig = config.get('database')` とそれに関連する箇所は、各環境に応じて変更してください。
- `src/health/health.module.ts` に置いていますが、場所は任意です。

```typescript:src/health/health.module.ts
import config from '@config'
import { Controller, Get, Module } from '@nestjs/common'
import {
  HealthCheck,
  HealthCheckResult,
  HealthCheckService,
  HealthIndicatorResult,
  TerminusModule,
  TypeOrmHealthIndicator,
} from '@nestjs/terminus'
import { TypeOrmModule } from '@nestjs/typeorm'

@Controller('healthz')
export class HealthController {
  constructor(
    private readonly health: HealthCheckService,
    private readonly db: TypeOrmHealthIndicator
  ) {}

  @Get()
  @HealthCheck()
  healthCheck(): Promise<HealthCheckResult> {
    return this.health.check([
      // Set the timeout for a response to 300ms
      (): Promise<HealthIndicatorResult> =>
        this.db.pingCheck('database', { timeout: 300 }),
    ])
  }
}

const dbConfig = config.get('database')

@Module({
  imports: [TerminusModule, TypeOrmModule.forRoot(dbConfig)],
  controllers: [HealthController],
})
export class HealthRestModule {}
```

```typescript:src/health/health.module.ts
// https://github.com/nestjs/config を使って TypeORM の設定をしている時の @Module 部分の例

@Module({
  imports: [TerminusModule, TypeOrmModule.forRootAsync(typeOrmModuleConfig)],
  controllers: [HealthController],
})
```


```typescript:src/app.module.ts
@Module({
  imports: [
    ConfigModule.forRoot(configModuleConfig),
    TypeOrmModule.forRootAsync(typeOrmModuleConfig),

    // REST modules
    HealthRestModule,  // この行を追加
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}
```

正常動作を curl で確認。

```shell
$ curl -X GET "http://localhost:3000/healthz"
{"status":"ok","info":{"database":{"status":"up"}},"error":{},"details":{"database":{"status":"up"}}}% 
```


# 上記以外の設定

[【NestJS】ヘルスチェック（v6版）](https://qiita.com/piggydev/items/922be61c323e047a90c1) を参考にしてください。
テストで使う自分のメールアドレスが枯渇。そんなあなたに

## システム開発でメールアドレスを登録しますよね、複数アカウント作りますよね。

a@example.com
b@example.com
などなど

## 自分のメールアドレスも無限に複製できるんです！！

maejimayuto@example.com
maejimayuto+01@example.com
maejimayuto+test@example.com

こんな感じで
`+` をアットマークの前に追加し、その後に適当な文字列を入力すればエイリアスメールアドレスの完成 🤯

## 今日からあなたもキーメーカー！
たくさんのメールアドレスを使って、アカウントを作りまくりましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123610/b529f0fa-b25e-525e-8cec-e77d383d2c8a.png)
【Rails】ドット(.)とか、コロン(:)とは一体

`::`とか、`.`とかよくお見かけします。
これはメソッドの呼び出しの違いで、表記が変わるという種明かしなんです。


#ドット記法

```ruby:
class User
  def method
    puts "Hello"
  end
end
```

```ruby:
> user = User.new

> user.method
Hello
=> nil
```

#コロン記法

```ruby:
class User
  def method
    puts "Welcome"
  end
end
```

```ruby:
> user = User.new
> user::method
Welcome
=> nil
```

###ドット記法とコロン記法の違い

ドット記法とコロン記法の違いは、`定数を呼び出せる`かどうか。

| 記法 | メソッドの呼び出し | 定数の呼び出し |
|:-:|:-:|:-:|
| ドット記法  | ○  | ×  |
| コロン記法  |  ○ |  ○ |



###Rubyでは、クラスやモジュールも定数として扱われる。

```ruby:
require 'uri'
require 'net/http'

url = URI.parse("http://yahoo.co.jp")
http = Net::HTTP.start(url.host, url.port)
```

```ruby:
> document = http.get(url.path)

> puts document.body
# ドキュメントを表示
```

#まとめ

このようにコロン記法だと、指定した別ファイルのクラス内やモジュール内のアイテムにアクセスすることができる。
GitHubの公式CLIを使ってissueをまとめて作成する

普段私達の開発チームはGitHubのProjectsを使ってissue（タスク）管理しています。
今回、一括でissueを登録する必要があり、ブラウザからポチポチやるのが手間だったので公式CLIを使ってみました。

投稿するまでもない内容ですが、また公式ドキュメント見るのも手間なのでメモレベルで投稿します。


# インストールする（Mac）
```terminal
$ brew install gh
```

# ログインする
ドキュメント
https://cli.github.com/manual/

```terminal
$ gh auth login

# あとは案内に従ってログイン
```

# issueを作成する
公式のドキュメントを見ると使い方は下記の通りのようです。
https://cli.github.com/manual/gh_issue_create

```example
$ gh issue create --title "I found a bug" --body "Nothing works"
$ gh issue create --label "bug,help wanted"
$ gh issue create --label bug --label "help wanted"
$ gh issue create --assignee monalisa,hubot
$ gh issue create --project "Roadmap"
```

※ GitHub上の対象プロジェクトは `.git/config` の中身を見ているっぽいです（未確認）

とりあえず適当にシェルファイルを作成する

```terminal
$ vim ./github.sh
```

ファイルの中身はこんな感じです。

```github.sh
gh issue create --title "ここにissueタイトルがはいります。その1" --body "
ダブルクォーテーションで囲めばbodyに
改行が使えます。
" --project 日本語でもプロジェクト名がはいります

gh issue create --title "ここにissueタイトルがはいります。その2" --body "
ダブルクォーテーションで囲めばbodyに
改行が使えます。
" --project 日本語でもプロジェクト名がはいります
```

そのシェルファイルを実行します

```terminal
$ sh github.sh
```

これで完了です。
【Gatsby.js】単一のjsonファイルを元に複数のページを生成する

Gatsby.jsを使って、jsonファイルから複数のページを生成する方法をまとめます。
Gatsby、情報自体はそこそこ豊富なんですが、日本語の情報が少ないですね。。

## 記事データをまとめたjsonファイルを作成
```zsh
$ mkdir src/data
$ touch src/data/articles.json
```
```src/data/articles.json
[
  {
    "slug": "how-to-use-gatsby",
    "title": "【Gatsby.js】「ここだけ押さえれば普通に使える」って知識をまとめてみた",
    "content": "Gatsby.jsでシンプルな静的サイトを作る際に必要な知識だけをまとめました。CMSとの連携等については今回は扱いません。本文テキスト本文テキスト本文テキスト本文テキスト本文テキスト本文テキスト",
    "tags": ["React", "Gatsby"]
  },
  {
    "slug": "learn-react",
    "title": "Reactの学習、今からやるならこうする",
    "content": "Reactの学習を初めて約2週間が経ちました。Railsの時と違って「とりあえずこれをやっておけば良い」ってものが見当たらずなかなか大変でしたが、試行錯誤の上色々と見えてきたのでまとめていきます。",
    "tags": ["React"]
  },
  {
    "slug": "restore-mac",
    "title": "Macの初期化→リストアを良い感じにする",
    "content": "Brewfile、Mackup、Docker、Dropboxを使って良い感じにリストアできる環境を作ったので、まとめます。以下の記事をめちゃくちゃ参考にしました。macOSでの開発環境を全部Docker化したらリストア時間が1時間半になった",
    "tags": ["Docker", "Brewfile", "Mackup"]
  }
]
```

## 記事のテンプレートページのベースを作成
```zsh
$ mkdir src/templates
$ touch src/templates/article.js
```
```jsx:src/templates/article.js
import React from "react"

export default () => (
  <>
    <h1>タイトル</h1>
    <p>本文</p>
    <span>タグ1</span>
    <span>タグ2</span>
  </>
)
```

## 記事を生成する処理を記述
```zsh
$ touch gatsby-node.js
```
```gatsby-node.js
const path = require("path")
const data = require("./src/data/articles.json")

exports.createPages = ({ actions }) => {
  const { createPage } = actions
  const template = path.resolve("./src/templates/article.js")
  data.forEach(article_object => {
    const path = `articles/${article_object.slug}`
    createPage({
      path, // 生成されるページのpath
      component: template, // ページのベースとなるテンプレート 
      context: article_object, // GraphQL経由で受け渡すデータのオブジェクト
    })
  })
}
```

## GraphiQLを開き、データを取得するためのクエリを作成
`gatsby develop`で開発サーバーを立ち上げ、ブラウザで http://localhost:8000/ にアクセスしてGraphiQLを開く。
`allSitePage > edges > node > context`と順に開いていくと、`title`、`content`、`tags`が見つかるのでチェックを入れて実行し、欲しいデータが取得できることを確認。

## GraphQLで取得したデータをテンプレートページに埋め込む
作成したクエリで必要なデータを取得し、テンプレートに埋め込みます。
GraphQLで取得したデータは`data`というオブジェクトに格納されるので、そこから値を取り出して出力します。

```jsx:src/templates/article.js
import { graphql } from "gatsby"
import React from "react"

export default ({ data }) => {
  const article = data.allSitePage.edges[0].node.context
  return (
    <>
      <h1>{article.title}</h1>
      <p>{article.content}</p>
      {article.tags.map(tag => (
        <span>{tag}</span>
      ))}
    </>
  )
}

export const query = graphql`
  query($path: String!) {
    allSitePage(filter: { path: { eq: $path } }) {
      edges {
        node {
          context {
            content
            tags
            title
          }
        }
      }
    }
  }
`
```

## 開発サーバーを再起動して確認
開発サーバーを再起動し、存在しないURLを入力して404ページを表示すると、ページ一覧に今作ったページが追加されていることが確認できます。

## 参考
- [Build a Multi-Page Gatsby Site from JSON - DEV](https://dev.to/ashleemboyer/build-a-multi-page-gatsby-site-from-json-3kp)
- [gatsby+cmsで動的にページを生成 - anotion](https://d0ne1s.anotion.so/9ae12252934043fbb4b3abac9c7e23fb)
【Swift】ちょっとはMVPという設計パターンに触れてみる

## なぜ書いたか
これまでSwiftを使って色々アプリを作ってきましたが、
正直設計パターンというのをほとんど意識しませんした:joy:
基本的なMVCと言われるもので作ってましたが、そろそろまずいだろということで
ちょっと設計パターンについて勉強してみました。

本記事はアウトプット用のメモとなります。

## MVCとMVPの違い
- MVC
 - Model
     - ドメインのモデルにあたる構造体を定義クラス
 - View
     - ViewControllerやTableViewCellクラスなど画面描画に関する処理を行うクラス
 - Controller
     - ViewControllerクラス　ユーザーからの操作の検知やその後の画面変更を行うクラス
- MVP
 - Model
     - 上記同様　構造体を扱うクラス
 - View
     - ViewCotrollerクラス　Uikitをインポートした画面描画に関する処理をまとめたクラス
 - Presenter
     - Presenterクラス　Uikitをインポートしないデータを扱うクラス

### MVPにおける各コンポーネントの責務

| モデル | ビュー | プレゼンター |
|:-:|:-:|:-:|
| DB層と通信する   | データをレンダリングする  | モデルへのクエリを実行します  |
| 適切なイベントの提起  | イベントを受け取る  | モデルからデータをフォーマットする  |
|   | 非常に基本的な検証ロジック  | フォーマットされたデータをビューに送信します。  |
|   |   | 複雑な検証ロジック  |

引用：https://riptutorial.com/ja/ios/topic/9467/mvpアーキテクチャ
 
#### MVCのデメリット（一部）
MVCではViewControllerがViewとControllerを兼ねて処理している
→Step数が多くなり肥大化しやすい。
 
MVPによる対処法：Presenterクラスを用いてViewControllerクラスの処理をPresenterクラスに一部移動する。
 
### MVPの恩恵
- ViewControllerのボリュームを抑えることができる。
 - 可読性の向上
- クラスごとの責務がわかりやすい
 - 保守性、静的テストのしやすさの向上
- 設計パターンを知っていれば、新規参入者でもわかりやすい構造

## 参考サイト
[iOSアプリ設計大全集 2016](https://qiita.com/tattn/items/d4b95af0b60c3849243a#mvp)
わかりやすくMVCやMVP、MVVMなどについてまとめられている
設計パターンの一覧を学ぶのに有用なサイト
[PEAKS（ピークス）｜iOSアプリ設計パターン入門](https://peaks.cc/books/iOS_architecture)
設計パターンの細かい説明だけでなく、設計とはという概念的な部分まで書かれた書籍
ネットで一部無料で見ることができる
[iOSをMVC,MVP,MVVM,Clean Architectureで実装してみた](https://medium.com/@rockname/clean-archirecture-7be37f34%E2%80%A6)
各設計パターンをメリットデメリットを上げてわかりやすくまとめられている
 
[筋肉.swiftアプリをMVPパターンで実装(しようと)してみて感じたこと](https://qiita.com/kboy/items/6b225eeeddf7f2c4777d)
[これまで自分が実装してきたMVPは中途半端だった](https://qiita.com/ARATAYOKOYAMA/items/c6042b5ddc0b51c9bd37)
MVPとは　について知れるサイト
 
https://github.com/rockname/ArchitectureSampleWithFirebase/tree/mvp
https://github.com/gdate/MVPTest
MVPの設計パターンにそったサンプルコード
ECサイトにおけるジャンル検索(customer側)

#1.　前提条件
```rails:app/models/genre
has_many :items
```
```rails:app/models/item
belongs_to :genre
```
genreとitemは1対多の関係となっています。
#2.genreコントローラ,view, route.rbの作成
以下のコードでジャンルのコントローラとshowページを作ります。
`$ rails g controller Genres show `

以下のコードをroute.rbに記載します。

```rails:config/route.rb
resources :genres, only: [:show]
```


以下のコードをgenre_controllerに記載します

```rails:app/controllers/genre_controller.rb
    def show
		  @genres = Genre.all
		  @genre = Genre.find(params[:id])
	end
```

#3.showページにgenreに基づいたitem一覧を表示させる

showページに以下のコードを記載

```rails:app/views/genre/show
<div class="item-index-box">

    <!-- ジャンル選択のサイドバー -->
    <%= render "items/genres_sidebar", genres: @genres %>
    <!-- ジャンル選択のサイドバー -->
    <div class="item-index">
    <h3>商品一覧</h3>
        <table>
          <tbody>
            <tr class="item-box">
              <% @genre.items.each do |item| %>
                <td class="item">
                    <%= link_to item_path(item) do %>
                      <%= attachment_image_tag(item, :image, :fill, 300, 300, fallback:"top.image.jpg") %><br>
            	      <%= item.name %><br>
            	      ￥<%= item.price %>
                    <% end %>
                </td>
              <% end %>
            </tr>
          </tbody>
        </table>
    </div>
</div>
```

@genre.itemsとすることでgenreに基づいたitem一覧を表示させることができる。
#5. 今回の実装で学んだこと
当初itemsコントローラ内にgenreアクションを追加し、ルートもresources:items内にしていたのだがそうするとルートがitemsのidを取ってしまう為、新たにコントローラとルートを付け加えた。
セル内改行に対応したcsvの読み込み

# 前回のあらすじ

[何も知らないところからのhtml、CSS](https://qiita.com/tenpoul/items/4ce608943421261c2638)

プログラム自体は出来ているが記事にするまでに相当時間が空いた。
前回はレイアウトを作ることができた。
今回はリストをつくるために元のデータを読み込む。

#csvを読み込むために。

ローカルファイルのcsvを読み込みたい。
しかし、調べてみるとボタン操作をせずにファイルを読み込むためにはgoogleChromeではできないようだ。
さらに調べるとNode.jsを使えば操作できるようだ。ついでにデスクトップアプリ作成のためにElectronを導入することになる。

今後は
- Node.js
- Electron
が導入されている環境を想定して記事を書いていく。

最終的な表示の都合上、読み込むcsv元データはセル内改行を行っているものを想定する。
Excel→csvに変換したものである。

csvファイルの読み込みに関しモジュールを導入した。
npm で導入できるので詳細は検索して欲しい。

- モジュール　fs　：ファイル読み込みのためのモジュール
- モジュール　iconv-lite　：文字コード変換のためのモジュール

というわけでカキカキした。

```
//csvセル内での改行コードに対応(行の最後のセルはセル内改行されていないこと)
var database =[[]];   //データを格納するための変数
const fs = require('fs');
const iconv = require('iconv-lite');
var filename = __dirname + '\\database.csv'   //ファイルパスを記載
const content = fs.readFileSync(filename);　　//ファイルの読み込み
var buf = new Buffer.from(content, 'binary'); //バイナリデータにする
var buf2 = iconv.decode(buf,"Shift_JIS");   //文字コード変換
var database_tmp = buf2.split(',');　　　//,で区切り列ごとに配列に格納
var line_no =0;
var data_no =0;
var line_tmp;
for(var i=0;i<database_tmp.length;i++){
      //行末尾の改行コードを判定し該当すれば行とする
      if(database_tmp[i].indexOf('"')==-1 && database_tmp[i].indexOf('\n')>=0){
         line_tmp = database_tmp[i].split('\n');   //末尾の改行セルを分ける
         database[line_no][data_no]=line_tmp[0];   ///分けたセルを挿入
         line_no = line_no + 1;    //配列の中で計算できないため外で変数計算
         database[line_no]=[];   //行要素に列用の配列を挿入する
         databse[line_no][0]=line_tmp[1];   //行の頭として分割した片割れを挿入
         data_no =1;
      }else{
         database[line_no][data_no] = database_tmp[i].replace('"','');
         data_no = data_no + 1;  
      }
   }
}

```

これで自分の想定しているデータはセル内改行に対応してした。
が、コメントに書いたようにすべての形には対応していないのでコピペする人は当然だがテストして下さい。
※行の最後のセルはセル内改行されていないこと
CSSのみでタブとタブコンテンツの表示・非表示を切り替える

HTMLコーダーさんのJSを使わないタブ切り替えが、シンプルな実装で素晴らしかったので忘備録的にメモ。

# 概要
* タブは『インプットボックス』＋『ラベル』を使用
* コンテンツエリアは常時非表示にしておく
* コンテンツエリアは選択されたときのみ表示する

# サンプルコード

動かしてないので不具合あるかもですが、こんな感じでした。

```html

<div class="tabs">
  <!-- タブ -->
  <input id="tab_1" type="radio" name="tab" checked="">
  <label class="tab_label" for="tab_1">月別</label>
  <input id="tab_2" type="radio" name="tab">
  <label class="tab_label" for="tab_2">週間別</label>
  <input id="tab_3" type="radio" name="tab">
  <label class="tab_label" for="tab_3">曜日別</label>

  <div class="tab_content" id="content_1">コンテンツ１</div>
  <div class="tab_content" id="content_2">コンテンツ２</div>
  <div class="tab_content" id="content_3">コンテンツ３</div>
</div>
```


```css

input[name="tab"] {
    display: none;
}

.tabs {
  width: 100%;
}

.tab_label {
  border-top: 1px solid #999999;
  border-bottom: 1px solid #999999;
}

.tabs input:checked + .tab_label {
  border-bottom: 2px solid #55C501;
}

#tab_1:checked ~ #content_1,
#tab_2:checked ~ #content_2,
#tab_3:checked ~ #content_3 {
  display: block;
}

.tab_content {
  display: none;
}
```
初めてのPHPバージョンアップ

PHPのバージョンがいつの間にか古かったので何番煎じかはわかりませんがその忘備録を取ります。
インストール方法はパッケージ管理システムの [homebrew](https://brew.sh/index_ja) を利用することにしました。

以下Macターミナルでのコマンド。

・PHPのバージョンを調べます。

```
$ php -v
```


・homebrewコマンドでPHP7のバージョンを検索します。

```
$ brew search php@7
```

・homebrewコマンドでバージョン7.4をインストールします。

```
$ brew install php@7.4
```
　
・.bash_profileに追加してパスを通します。

```
$ echo 'export PATH="/usr/local/opt/php@7.4/bin:$PATH"' >> ~/.bash_profile
$ echo 'export PATH="/usr/local/opt/php@7.4/sbin:$PATH"' >> ~/.bash_profile
```

・PHPを再起動します。

```
$ brew services start php
```

・ターミナルを再起動してから$ php -vで再度バージョンを確認します。
　PHPのバージョンが7.4になっていれば成功です。

というのも、前回作ったBMIを計算する簡単なandroidアプリを作り、次はその結果をデータベースに結果を保存させてみようと思い至りました。
以前学んだPHPの復習も絡めてデータベースの使い方を学ぼうとして、それなら今度はフレームワークのlaravelを使ってみたいなと思い、絶賛遠回りをしている次第です。

早速laravelをインストールしようとしましたが、PHPのバージョンが7.1のため
インストール出来ないという初歩的な壁にぶち当たりました。（N回目）
相関サブクエリの練習

以下の画像のテーブルを使用する。
![スクリーンショット 2020-09-24 17.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/6b09645d-8121-3ffc-a801-4c5be141ec06.png)

商品分類ごとに平均販売単価より高い商品を商品分類グループから抽出する。

まずは商品分類ごとの平均単価を出してみる。

````sql
select shohin_bunrui,  avg(hanbai_tanka) from Shohin group by shohin_bunrui;
````

![スクリーンショット 2020-09-24 17.37.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/d5be1f6c-6c7c-cf5f-2184-741de9eeca9b.png)

相関サブクエリを使って抽出を行う。

````sql
select * from Shohin s1
where hanbai_tanka > 
(
    select avg(hanbai_tanka) from Shohin s2 
    where s1.shohin_bunrui = s2.shohin_bunrui
    group by shohin_bunrui
);
````
![スクリーンショット 2020-09-24 17.54.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/8fc725ff-558d-a567-e761-06c2c64ca0a6.png)


相関サブクエリはテーブル全体ではなく、
テーブルの一部のレコード集合に限定した比較をしたい場合に使用するようだ。

次は商品分類ごとの平均単価列を抽出してみる。

````sql
select shohin_id, shohin_mei, shohin_bunrui, hanbai_tanka, 
(
    select avg(hanbai_tanka) from Shohin as s2 
    where  s1.shohin_bunrui = s2.shohin_bunrui
    group by shohin_bunrui
) as hanbai_tanka_all 
from Shohin as s1;
````

![スクリーンショット 2020-09-24 18.07.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/0c79eb6f-db6e-516d-745a-bdfb472bd3ff.png)


こちらを参考にさせていただきました。
<a href="https://www.amazon.co.jp/dp/B01HD5VWWO/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1">SQL 第2版 ゼロからはじめるデータベース操作
</a>
[Laravel]Carbonで月初から月末まで何週あるか取得する

週別の集計結果を表示する必要があったため忘れないようメモ。

# サンプルコード
月初から月末まで何週あるかCarbonで取得。

```php
$start = new Carbon()->firstOfMonth();
$end = new Carbon()->endOfMonth()

getWeekOfNumberInMonth($start, $end);
```

```php
function getWeekOfNumberInMonth($start, $end) {
    $dt = $start->copy()->firstOfMonth();
    $week = 1;
    for($dt; $end >= $dt; $dt->addDay()) {
        if ($dt->isSunday() && $dt !== $start) $week++;
    }
    return $week;
}
```


FYI：
既出記事ですが取得ロジックを変えてやってます。
https://qiita.com/fabled/items/2607186731adc75f11e1
Svelteで「XXX has unused export property 'XXX'...」と出たときの対処方法

# はじめに
とあるSvelteライブラリのドキュメントサイトをローカル環境で動かしてたところ(Contribute目的で)ログ上で
`XXX has unused export property 'XXX'. If it is for external reference only, please consider using export const answer`という警告ログが出ていた。
その時の対処方法を記事にする。

# 再現

unused export propertyと記載されている通り、プロパティ渡し先のコンポーネントで宣言はしてるけど、使用していないときに起こるようです。

index.svelte

```javascript

<script>
  import Nested from './Nested.svelte';
</script>

<Nested count={10}/>
```

Nested.svelte

```javascript
<script>
	export let count;
</script>

```

そうすると、、、

![Warning](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325401/20c1f366-b9e4-a4e7-d29d-f7c39358aa35.png)

警告ログを確認することができました。

# 対応

今回の場合まったく使用してないプロパティなので、渡してる部分と宣言してる部分を削除することで警告ログは消える。
もちろん警告ログなので、放置していてもおそらく動作上に問題ないかと思います。（すごく気にはなるかと思いますが）
Unityのバージョンで躓いたOculusQuest開発

#1.はじめに
技術研究として2019年12月に実装された、OculusQuestのハンドトラッキング技術を用いた開発を行いました。
環境構築の部分で躓いてかなり時間を持ってかれたので備忘録としてまとめようと思います。
ちなみに開発したものはこちら ↓
・https://lab.taki.co.jp/virtual-cube-puzzle/

#2.開発環境
・Windows10
・Unity
・OculusLink
・AndroidSDK
・JDK

基本部分はググれば先人の方々がまとめてくださっているものがたくさんあるので最初はそちらを見るといいと思います。
それらを読んで上手くいけば万々歳です。
私は下記の記事を参考にさせていただきました。
躓いた部分以外は記事の内容の手順で上手くいきました。
・https://framesynthesis.jp/tech/unity/oculusquest/
・https://qiita.com/Kujirai_sakananosuke/items/f88e757eb7c70cdb1e4e

#3.躓いた部分
タイトルにも書いた通りUnityのバージョン関係で躓きました。
公式のサイトには推奨バージョンは2018.4 LTSまたは2019.3と記載されていました。
私もそれに沿って開発を始めたのですが手のオブジェクトが表示されなかったり、ビルドエラーを吐かれたりで全く上手くいきませんでした。
調べると色んな人が色んなバージョンで上手くいっていてどれが正しいのかわからず困りました。
ビルドができる＋ハンドトラッキングの開発ができる＋OculusLinkで実機確認ができるという3点が必要だったのですが、調べて出てきたバージョンでは3点完璧に上手くいくバージョンはありませんでした。
もう片っ端から試すしかねぇとなりヒーヒー言いながら色んなバージョンで確認して見つけました。
###Unity2019.4.3f
3点全部上手くいきました。
やっと落ち着いて開発を始めることができました。

#4.まとめ
ググった時に色んなバージョンでの開発の情報があるのは使用機材によって変わるからなんでしょうか。
Unityに不慣れなのもありますが、今回のVR開発で環境構築が一番疲れた気がします。
もしかしたら他の人では2019.4.3fで上手くいかないのかもしれませんが、誰かのお役に立つかもと思い記事を書きました。（こうしてまた1つ迷わせる情報が増えたのかもしれない…）
【Salesforce】承認プロセスでの複数ユーザによる全員承認について

#承認プロセスの複数ユーザによる承認

　Salesforceの承認プロセスには、特定個人の承認のみで承認されるパターンと、
　承認依頼された複数ユーザ（またはキュー）の承認が完了して、初めて承認されるパターンがあります。

　今回挙げるのは、「複数ユーザによる承認」についてです。

#複数ユーザによる承認についての基本情報

　下記は承認プロセスの設定画面の一部を抜粋したものです。

　選択肢の中から「自動的に承認者を割り当てる。」を選択すると、追加の設定項目として
　「複数の承認者が設定された場合」が表示されます。

　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657185/917bb077-7815-046c-89e4-6f86344c7aa4.png)

　◆最初の返答に基づいて承認または却下する
　　承認者が複数割り当てられていたとしても、一番最初に「承認or却下」した方の操作が反映されるパターン

　◆選択したすべての承認者から全員の承認を得る必要がある
　　承認者が複数割り当てられていた場合、全員の承認を得られなければ却下扱いとするパターン


#全員の承認が必要な場合について仕様の再確認
　
　「◆選択したすべての承認者から全員の承認を得る必要がある」について、仕様について改めて記載します。
　　選択リストから選択可能なのは・・・・
　　　・ユーザ
　　　・キュー
　　　・カスタマーポータルユーザ
　　　・関連ユーザ
　　の以上４つです。

　　この中で「キュー」についての仕様が一部誤解されていることがあったため、正確な仕様を記載します。

　　キュー：
　　　**正：キューに割り当てられた場合、キューに登録されているユーザのいずれか１名が承認or却下した時点で**
　　　　　**割り当てられたキュー全員の総意として判断される。**
　　　
　　　**誤：キューに割り当てられた場合、キューに登録されているユーザ全員が承認する必要がある。**
　　　　※承認プロセスの説明にある「選択したすべての承認者」のについて、キューであっても１名と扱われる。
　　　　　もしキューで管理したいのであれば、複数のキューを承認の割り当て先に複数行で指定する必要がある。

　　以上の仕様から「１つのキューを用意してそのキューに所属する全員の承認が得られるまで承認させない！」という
　　設計を考えている方がいたら注意してください。

#番外編
　
　上記の例で承認者に複数のキューを指定する例を挙げましたが、
　割り当てられたキューに登録されたユーザが存在しなかった場合、承認プロセスがどうなるかも併せて確認しました。

　結果：
　　登録されたユーザがいないキューであっても承認される待つ状態になるため、承認プロセスが進まなくなります。
　　※プロセス側からしてみれば、言われた通りキューに割り当てただけで、中身までは考慮しないということですね。

　上記方法でキューを承認者に指定する場合は、必ずユーザを登録するようにしてください。
PTX Compiler API のメモ

CUDA 11.1 から, (ひっそりと) PTX compiler API が追加されました.

https://docs.nvidia.com/cuda/ptx-compiler-api/index.html

PTX のコンパイルをドライバ側ではなく, Toolkit ライブラリ側で行います.
(ドライバ側でコンパイルだと, 古いドライバだと最新の PTX 機能が使えないなどがあるとドキュメントにあります)

PTX compiler API 自体は static library です. 自前アプリに組み込んで配布が可能となります.

コンパイルされた elf バイナリが取得できるので, 自前でキャッシュ関連の実装が必要ですが, PTX JIT compile 結果のキャッシュができるようになります.

## 使い方

CUDA Toolkit の samples にサンプルコードがなくてつらいです :cry:

API はそんなに多くないので, ドキュメントにあるサンプルコードで事足りるでしょうか.
とりあえずサンプルコードが動くのを確認しました.

PTX Compiler API 自体は CUDA API に依存していないので, PTX compile 自体だけなら cuda 関連のヘッダのインクルードやライブラリのリンクは不要です.
Linux の場合, 最低限 pthreads と libm のリンクが必要です.

### 再配布可能なライセンス

https://docs.nvidia.com/cuda/eula/index.html 

にあるように, `libnvptxcompiler_static.a` は, (自身のアプリに組み込んで)再配布可能になっています.
(cudart.dll など動的ライブラリも実は再配布可能なのですね)

## CUDA -> PTX の作成

PTX compile をクライアント側で処理するなら, cu -> PTX も NVRTC や nvcc とかではなく自前で JIT コンパイルしたくなりますね.

Clang で CUDA コードを NVPTX に変換するメモ
https://qiita.com/syoyo/items/4e60543aded0210fde49

libclang を使えば, libcuda 非依存で, 自前アプリに .cu -> .ptx の JIT コンパイル機能も追加できるはずです!

libClang/LLVM で C++ コードの JIT コンパイルを行う.
https://qiita.com/syoyo/items/486ce53a0dd7a8c73d71


### CUDA C++ STL?

https://github.com/NVIDIA/libcudacxx

libcxx をベースにした CUDA 用の C++ Standard Library があります.
が, 現状提供されているのは atomic とかだけです.

`std::vector` とかのコンテナは提供されていないため, C++ STL 相当すべてが使えるわけではないことに注意ください.
CodeWarでの勉強

##この記事について
最近始めたCodewarを通じて学べたことを少しずつアウトプット



##学び① joinメソッド

>Write a function that accepts an array of 10 integers (between 0 and 9), that returns a string of those numbers in the form of a phone number.


```ruby
#僕の回答
def createPhoneNumber(numbers)
  return "(#{numbers[0]}#{numbers[1]}#{numbers[2]}) #{numbers[3]}#{numbers[4]}#{numbers[5]}-#{numbers[6]}#{numbers[7]}#{numbers[8]}#{numbers[9]}"
end

#理想の回答
def createPhoneNumber(str)
  "(#{str[0..2].join}) #{str[3..5].join}-#{str[6..10].join}"
end
```

###解説
https://docs.ruby-lang.org/ja/latest/method/Array/i/join.html

僕が書いたコードでは配列のデータをバカ丁寧に一つ一つ文字展開をしている
理想のコードでは`str[0..2]`のようにまとめてやって、尚且つその配列の要素を結合して一つの文字列に変換するために`joinメソッド`を使用している。
MVVM Show View パターン2 Commandパラメータ

## 参考コード
ICommandインターフェイスを実装したコマンドを利用して、表示します。

MVVM_WindowCommands
https://github.com/mike-eason/MVVM_WindowCommands
のコードを見てみましょう。

## View
コマンドを指定して、そのパラメータにウインドウ名を指定しています。

```C#
  <Button Content="Open Window"
                    Command="{Binding OpenWindowCommand}"
                    CommandParameter="{x:Type local:TestWindow}"/>
```

## ViewModel
OpenWindowCommand

```C#
   public class MainWindowViewModel
    {
        public OpenWindowCommand OpenWindowCommand { get; private set; }
        public ShowDialogCommand ShowDialogCommand { get; private set; }

        public MainWindowViewModel()
        {
            OpenWindowCommand = new OpenWindowCommand();
            ShowDialogCommand = new ShowDialogCommand(PostOpenDialog, PreOpenDialog);
        }
```


## Commandクラス(Modelに該当する部分?)
ここで、Showしています。
ViewとViewModel以外は、すべてModelと考えますから、この部分もModelという認識で良いと思いますが、どうでしょうか。(VMのコードで、modelに相当するものではなく、単にView・ViewModelではないという意味で）

```C#
   public class OpenWindowCommand : ICommand
    {

        protected virtual void OpenWindow(Window wnd)
        {
            wnd.Show();
        }
```

## 分からない点
この処理の流れで、TestWindowを確定して表示を行っているのはどこでしょうか？
Viewでしょうか、ViewModelでしょうか、OpenWindowCommandでしょうか？
これは、**x:Type local:TestWindow　とTestWindowと名前を指定しているViewだと私は考える**のですが、違うのでしょうか？
ViewModelも、OpenWindowCommandも、引数を与えられて処理を行う部分ですから、TestWindowと確定しているわけではありません。
従って、TestWindowというViewを知っているのは、ViewのMainWindowだと私には思えます。そうすると、基本パターン1と、同じですね。基本パターン1はコードビハインドで、Viewから指定したViewを表示していますが、このパターンは、XAMLでコマンドを利用して、Viewから指定したViewを表示します。

## TestWindowを指定するところを変更する場合
けれども、XAMLで

```XAML
CommandParameter="{x:Type local:TestWindow}"
```

を指定せず、

* MainWindowViewModelでTestWindowを指定する　→　VMが他のViewを知っている
* OpenWindowCommandでTestWindowを指定する　　→　Mが他のViewを知っている

ことになると考えますが、この考え方で合っているでしょうか。

## 記事予定

* パターン1　[Viewのコードビハインド](https://qiita.com/hiro_t/items/967146f2ccb79318397c)
* パターン2　Commandパラメータ（この記事）
* パターン3　[Prism の Dialog Service](https://qiita.com/hiro_t/items/61a50d9f6308195c3536/)
* パターン4　引数を渡す（予定）
AWS SageMakerで既存のendpointを呼び出す

# 概要

SageMakerでendpointを立ち上げ、他のnotebookなどで使用したい場合の指定方法を示す。

# コード
引数にendpoint_nameを指定する。
endpoint_nameはAWSコンソール->SageMaker->推論->エンドポイントで確認できる。

## MxNet

```python

import sagemaker
predictor = sagemaker.mxnet.model.MXNetPredictor(endpoint_name="mxnet-training-*")
```

## PyTorch 

```python

import sagemaker
predictor = sagemaker.pytorch.model.PyTorchPredictor(endpoint_name="pytorch-training-*")
```

# おわりに
notebookが落ちてしまった場合や新しいnotebookで使うことができるようになります。
Github ActionsでDockerイメージをpullしてtestを行うJobを作成してみる手順


今回はPythonのプロジェクトのリポジトリを ``Github Actions`` で ``pytest`` を ``docker-compose`` のイメージ上で行う為の練習を行ったのでそのメモを記載します。

# 前提条件
- Github の packages のトークンを作成しておく。
- docker login しておく。
- Github の 任意のリポジトリに``Secrets``をpackages操作可能なトークン番号を登録しておく。<br>(私の環境では``GHCR_IO_TOKEN``という名前で登録している。) 

# フォルダ構成
```bash

repository/             # リポジトリディレクトリ
　├ .github/
　│　├ workflows/
　│　│　└ sample.yml     # Github actionsのファイル
　├ project/
　│　├ sample/           #（説明省略）
　│　│　├ __init__.py
　│　│　└ add.py
　│　└ test/             #（説明省略）
　│　　　├ __init__.py   
　│　　　└ test_add.py
　├ docker-compose.yml   # 後ほど詳細記載
　├ Dockerfile           # 適当なPythonイメージ（説明省略）
　└ requirements.txt     # 適当なパッケージを記載（今回はpytestのみ記載している）
```

# 手順

1. docker-compose.ymlにimageを ``ghcr.io`` 指定したイメージ名を記載する。
2. ``docker-compose up`` でイメージを作成後、``docker-compose push`` してイメージをPushする
3. github actionsのファイルで pull して pytestを行う！

# イメージをghcr.ioに上げる。
以下のようにイメージを指定する。

```yml:docker-compose.yml
 services:
    python:
        build: .
        #image: ghcr.io/Githubのユーザー名/リポジトリ名/イメージ名:タグ名
        image: ghcr.io/n-jun-k2/sample-actions/python:v1

```
ローカルでイメージを作成し、Pushする。

```bash
# とりあえずいつもの様にイメージを作成
docker-compose up -d 
# イメージをPush
docker-compose push
```

# Github Actions のCIファイルについて

``...``は適当に変えてください。
チェックアウトしてログインしてpullしてpytestを行っています。

```yml:.github/workflows/sample.yml
name: ...
on:
  ...

jobs:
  ...:
    name: ...
    runs-on: ubuntu-20.04
    steps:
        - name: Checkout                                         # チェックアウトして
          uses: actions/checkout@v2
        - name: Login to Docker                                  # docker login　して
          uses: docker/login-action@v1
          with:
            registry: ghcr.io
            username: ${{ github.repository_owner }}
            password: ${{ secrets.GHCR_IO_TOKEN }}
        - name: Set up Docker                                    # pull してイメージを立ち上げ
          run: |
            docker pull ghcr.io/n-jun-k2/sample-actions/python:v1
            docker-compose up -d
        - name: Run test                                         # pytestを行う。
          run: docker-compose exec -T python pytest

```
このCIファイルでdocker-composeイメージ上でpytestが行われる。

注意すべき点は、以下の`` -T ``のオプションを入れ忘れないように！エラーになっちゃうよ

```bash
docker-compose exec -T python pytest
```
【Python】多次元配列に値を代入するときの注意点

## やりたかったこと
動的計画法に関する問題で，初期化した2次元配列(dp)に対して，ある数字(60)を代入しようとしていた．

[問題]  Atcoder EDPC C-Vacation(https://atcoder.jp/contests/dp/tasks/dp_c)

以下のようなコードを書いていた．

```python
dp=[[0,0,0]]*5
print(dp)
#出力 [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]

a=[10,40,70]
dp[0]=a
print(dp)
#出力 [[10,40,70],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]


# 以下が問題のコード#######
dp[0][1]=60
print(dp)
#出力 [[10,40,70],[0,60,0],[0,60,0],[0,60,0],[0,60,0]]
```

本当はdp[0][1]の所だけに60を代入したかった．(以下)

```python

print(dp)
#出力 [[10,40,70],[0,60,0],[0,0,0],[0,0,0],[0,0,0]]
```

## 原因
以下のようにリストを初期化してしまうと，要素であるリストが全て同じオブジェクトとして生成されてしまう．(以下)

```python
# ダメな例1
dp=[[0,0,0]]*5

# ダメな例2
dp=[[0]*3]*5

```

## 解決法
以下のように，「<b>内包表記</b>」 でリストを初期化すれば，全て異なるオブジェクトとして生成できる．

```python

dp=[[0]*3 for i in range(5)]
dp[0][1]=60
print(dp)
#出力 [[10,40,70],[0,60,0],[0,0,0],[0,0,0],[0,0,0]]
```

numpyなら楽にできる

```python
import numpy as np

dp=np.zeros((5,3))
dp[0,1]=60
print(dp)
#出力 array([[ 0.,  0.,  0.],[ 0., 60.,  0.],[ 0., 0.,  0.],[ 0., 0.,  0.],[ 0., 0.,  0.]])
       
```

## まとめ
list型で多次元配列を初期化するなら，内包表記を使う．
ただし，numpyで初期化する方が楽．

### 参考
https://note.nkmk.me/python-list-initialize/
BFE.dev解答記録 #23. sum()を実装する

> https://bfe.dev/ja はFrontEnd版のLeetCode、GAFAの面接を受けるなら練習した方がいいかなと。
> 以下は自分の練習記録です。

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7f1pk8o1zlzgnipxnzk2.png)

[BFE.dev#23. sum()を実装する](https://bigfrontend.dev/ja/problem/create-a-sum)をみてみよう

## 問題

以下の条件を満たす前提で`sum()`を実装してください。

```js
const sum1 = sum(1)
sum1(2) == 3 // true
sum1(3) == 4 // true
sum(1)(2)(3) == 6 // true
sum(5)(-1)(2) == 6 
```

## 分析

上記の用件からわかること

1. `sum()` は引数を受けるfunctionを返す
2. `sum()` では渡した引数を全部足して、1を繰り返す
3. type coercionで、function == numberは可能。`valueOf` か `toString`を実装する必要

## Let's code

まずfunctionを返す部分を作りましょう。引数の和を一時的に保存するために、2番目の引数にしたらいい。

```js
function sum(num, currentSum = 0) {
  const newCurrentSum = num + currentSum
  
  const func = function(arg) {
    return sum(arg, num + currentSum)
  }

  return func
}

```

最後に`valueOf`を入れれば完成

```js
function sum(num, currentSum = 0) {
  const newCurrentSum = num + currentSum
  
  const func = function(arg) {
    return sum(arg, num + currentSum)
  }
  
  func.valueOf = () => newCurrentSum
  // below also works
  // func.toString = () => newCurrentSum.toString()
  
  return func
}
```

## 通った！

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mnu1x90u5pvv7xcu411q.gif)

もし興味あれば、 BFE.devでやってみましょう https://bigfrontend.dev/ja/problem/create-a-sum
Power Automateでテキストファイルを読み込む

Office365にも付随しているPower Automateで、OneDrive等に配置されたテキストファイルの中身のテキストデータを、フロー中に使用したいときにどうするか、という記事です。

本記事では、サンプルとして、以下の要件を満たすフローを作成してみます。

* OneDriveの特定のディレクトリにファイルが新規作成されたら、そのファイルの中のテキストデータをメール本文として、メールを送信する
* テキストファイルの中身は、HTML形式とする

メール送信アクションの性質上、テキストファイルの中身はHTMLとします。

なお、本記事では、ファイルの配置場所をOneDrive for Business、メール送信はOffice 365 Outlookを使用します。（通常のOneDriveやSharePointでも、同じことはできると思いますが、未検証です。）

# フロー図

![フロー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84550/62966086-957c-16f6-57b3-85c7af3b743f.png)

# トリガー: ファイルが作成されたとき

「OneDrive for Business」コネクタの、「ファイルが作成されたとき」トリガーを使用します。マイクロソフトのドキュメントは[こちら](https://docs.microsoft.com/ja-jp/connectors/onedriveforbusiness/#when-a-file-is-created)。

`フォルダー`引数には、OneDrive for Businessの任意のフォルダを指定します。`サブフォルダーを含める`引数を`はい`にすると、手前で指定したフォルダ直下のみでなく、サブフォルダに作成されたファイルもトリガーの対象となります。`コンテンツタイプの推測`は、通常は`はい`にします。

![トリガー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84550/ea1ae856-0c4f-7208-b539-a0de0cae01a9.png)

本記事では、常にテキストファイルが新規作成されることを前提にしていますが、そうでない場合は、コンテンツタイプの推測結果をもとに、条件分岐等を挟むことも考えられます。
なお、テキストファイルについては、Power Automateでは、自動的に「UTF-8で符号化されているテキストファイル」であると判断するようです。よって、Shift-JIS形式のテキストファイルから文字列を抽出することは、おそらくできない（文字化けが発生する）と思われます。
（下記参考ページで、文字化けを回避する方法が紹介されていますが、テキストファイルを別のディレクトリへコピーするという用途向けの解説のため、今回の用途向けではありません。）

参考: [Power Automate でテキストファイルの文字化けを回避する](https://jpdynamicscrm.github.io/blog/powerautomate/Avoid-Character-Corruption-Methods/)

# アクション1: 変数を初期化する

手前のトリガーによって、ファイルコンテンツが取得できるのですが、そのままだと、一律でバイナリ形式として認識され、直接、メールの文面に使用できません。しかし、「変数を初期化する」アクションを使用して、このファイルコンテンツを値とした文字列変数を定義すると、当該変数の値には、テキストファイルの中のテキストがそのまま入るようです。

`名前`引数には、文字列変数につける好きな名前を指定します。`種類`引数は文字列にします。`値`引数には、手前のトリガーで取得されたファイルコンテンツを指定します。

![アクション1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84550/c557d7f4-692a-a93c-4295-69f92226666d.png)

参考: [How to read unknown text file namess with flow](https://powerusers.microsoft.com/t5/Building-Flows/How-to-read-unknown-text-file-namess-with-flow/td-p/426229)

# アクション2: メールの送信(V2)

マイクロソフトのドキュメントは[こちら](https://docs.microsoft.com/ja-jp/connectors/office365/#send-an-email-(v2))。

`宛先`・`件名`引数には、任意の値を指定します。`本文`引数には、手前で定義した変数を指定します。その他の引数は、必要に応じて指定します。

![アクション2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84550/13858f1c-7d08-f423-fdf7-22cfc97fda54.png)

# 試してみる

トリガーで対象としたディレクトリに、以下のようなテキストファイルを新規作成してみます。

```text:テストファイル.txt
これはテストメールです。<br/>
この文は、テキストファイルの文章です。
```

![OneDrive](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84550/af8ea27c-efda-7353-ad92-97d3131dcd3f.png)

すると、数分後に、指定した宛先にメールが飛んできました。（ ~~本題とはずれますが、本記事で使用した「ファイルが作成されたとき」トリガーはすぐには発動されず、10分～20分程度かかる場合もあるようです。~~ 2024年4月現在は、ファイルが作成されたかどうかを確認する頻度を設定できるようなので、すぐ発動させることもできる様子です。）

![メール](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84550/65288ebc-328e-baf9-9e67-5f5ffa5a9082.png)
jest-puppeteerでignoreHTTPSErrors:trueを設定する方法

puppeteerにはSSL証明書のエラーを無視するオプション（ignoreHTTPSErrors: true）があります。jest-puppeteerを介して動作させている場合にオプションを設定する方法を調べました。

jest-puppeteer.config.jsを作成してください。

```javascript:jest-puppeteer.config.js
module.exports = {
  launch: {
    ignoreHTTPSErrors: true
  }
}
```

## 参照

* jest-puppetterのリファレンス https://github.com/smooth-code/jest-puppeteer#configure-puppeteer
* puppeteerのリファレンス https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#puppeteerlaunchoptions
Android: YouTube Android Player API

- Android Studio 4.0.1
- Kotlin 1.4.0
- YouTube Android Player API 1.2.2

YouTube Android Player APIを使って、AndroidアプリでYoutubeを再生させます。

## Android Studioでプロジェクト作成



## アプリの登録

Google APIsでAPIキーを作成し、Androidのプロジェクトと関連付けます。

### Android Studioでプロジェクト作成

プロジェクトを作成し、パッケージ名を決めます。

### アプリのフィンガープリント取得

SHA-1のフィンガープリント取得方法

- AndroidStudioで、Gradleタブの「app/Tasks/android/signingReport」をダブルクリック
- Runコンソールに出力される


### Googleプロジェクト作成
https://console.developers.google.com/cloud-resource-manager

既存のプロジェクトを利用してもいいかもしれませんが、作成します。
[リソースの管理](https://console.developers.google.com/cloud-resource-manager)から、プロジェクト作成

### APIキー作成

https://console.developers.google.com/apis/credentials

作成したプロジェクトで
「＋認証情報を作成」 → 「APIキー」 → 「閉じる」

### アプリと関連付け

作成されたAPIキーを選択
APIキーの名前をAPIキー1から、適当に変更

Android アプリに使用を限定、のメニューから
「項目を追加」パッケージ名とSHA-1のフィンガープリントを設定

## ライブラリのダウンロードとセットアップ

### ライブラリのダウンロード
https://developers.google.com/youtube/android/player/downloads

### Androidプロジェクトに登録

- ダウンロードしたzipファイルからjarファイルをコピー
libs/YouTubeAndroidPlayerApi.jar
→ [Project Folder]/app/libs

- AndroidStudioで、Porject/app/libs/YouTubeAndroidPlayerApi.jarを
右クリック「 Add As Library...」→ appを選択




## アプリ実装

### パーミッション設定

```xml:AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
```

### 回転制御

```xml:AndroidManifest.xml
<activity android:name=".MainActivity"
          android:configChanges="orientation|screenSize|keyboardHidden">
```

### レイアウトXML編集

- Designに切り替え、Containers/<view>をレイアウトにドロップすると、Viewクラスの選択ダイアログが表示される
- YouTubePlayerView(com.google.android.youtube.player)を選択
- ViewにIDを付ける（今回はyoutubeView）

※YoutubePlayerViewにボタンなどが重なっていると、再生が途中で止まってしまいました。


### Activity実装

YouTubeBaseActivityを継承

```kotlin:MainActivity
class MainActivity : YouTubeBaseActivity() {

	val API_KEY = "[API_KEY]"

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContentView(R.layout.activity_main)

		val playerView = findViewById<YouTubePlayerView>(R.id.youtubeView)
		val listener = object: YouTubePlayer.OnInitializedListener {
			override fun onInitializationSuccess(provider: YouTubePlayer.Provider?, player: YouTubePlayer?, wasRestored: Boolean) {
				player?.loadVideo("[YoutubeのVideoID]")
			}

			override fun onInitializationFailure(provider: YouTubePlayer.Provider?, result: YouTubeInitializationResult?) {
			}
		}
		playerView.initialize(API_KEY, listener)
	}
}
```
[自分用] ボウリングにお役立ちアプリ(Swift-iOSアプリ)

#Swiftでアプリを作ってみた
Swiftの練習として, Userdefault, webAPI(Qiita), スクレイピングを利用したアプリを作成してみました.
アプリの内容としては, やくに立たないアプリよりも自分の役に立つアプリを作ろうと考えて趣味のボウリングに役立つアプリを作りました. 

![Sep-24-2020 17-31-17.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543995/8c77f222-a3d9-7b5e-106c-5859e70163f0.gif)

githubのリポジトリはこちらです
https://github.com/yossi1118ubi/Bowling4

##機能まとめ
1. webAPIを使って最近のボウリングに関するブログを検索する機能
2. 自分で作成したボウリングに関する参考になる記事をまとめたスプレットシートから内容を検索して引っ張ってくる機能
3. 一般的なメモ機能
4. 行きつけのボウリング上の営業時間を表示する機能



##それぞれの機能紹介
###1. webAPIを使って最近のボウリングに関するブログを検索する機能

プロボウラーなの上げている最新のブログを簡単に探すことができるといいなと思い, webAPIを使ってボウリング関連のブログを取得する機能を作りました. 本当はnoteのAPIを使って情報を取得しようと思っていたのですが, APIが公式には公開されていないとのことで仕方なく
QiitaのAPIでボウリングに関する最新の記事を取得するアプリを作りました. 

結局, ボウリングに関する技術的な記事を返してくれる機能となってしまい全然嬉しくない機能となりました. 
この機能を開くと初期ではボウリング関連の最新記事がtableViewに表示されます. 
また, 好きなキーワードで検索をすることもできます. また, 特定のtableViewの行をタップするとSafariでその記事を見ることができるという機能も追加しました. 


この機能では, webAPIの使い方を学びました. 

![Sep-24-2020 17-39-43.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543995/6d9bfc83-9e34-4eff-9c42-56bd4ea17954.gif)


![Sep-24-2020 17-38-02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543995/9dd2967e-601d-95a3-6ccc-1574ac5e19eb.gif)



###2. 自分で作成したボウリングに関する参考になる記事をまとめたスプレットシートから内容を検索して引っ張ってくる機能

個人的にボウリングで気になった動画や記事のタイトルとURLをスプレットシートに記録していたので, その記事を検索してひっぱってきてくれる機能が欲しいと考えました. 
そこで, jsonを使ってスプレットシートの情報を獲得できるようにしました. 
また, そのタイトルをタップするとそのURLの記事や動画をSafariで表示することができます. 

この機能では, JSONの使い方を勉強しました. 



###3. メモ機能
本当に一般的なメモ機能です. メモを保存書いて保存する機能, 保存したメモを見る機能, 保存したメモを削除する機能が搭載されています. 
この機能を通して, アプリ内へのデータ保存の仕方(Userdefaultの使い方)を勉強しました. 

![Sep-24-2020 17-46-28.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543995/fddd3213-1147-f4b3-eaae-5705e72d518c.gif)




###4. 行きつけのボウリングの営業時間を表示する機能
コロナで行きつけのボウリング上の営業時間が変わることがあったので, 簡単に確認できるような機能を作りました. この機能は, 行きつけのボウリング上のwebサイトからスクレイピングで営業時間を取得して画面に表示する機能です. 

この機能を通して, スクレイピングの手法を学びました. 


![Sep-24-2020 17-49-41.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543995/42ae568f-e4b6-f24a-2659-9d5ea1755b23.gif)
RockyLinuxにOpenLiteSpeedを入れる。


といってもそんなに難しい物ではないので気楽に行きましょう。
CentOSは最小限の構成でインストールします。動作にはメモリ1GBでも良いのですが、後述するPHPのコンパイルでメモリ不足になりますので2GBほど用意した方が良いでしょう。（デフォルトが「サーバーGUI付き」になっているので要注意）
さてここからが本番です。（2022年6月21日の時点では）V1.6、V1.7の2ラインで走っているようです、~~V1.7では設定項目が反映されないなどの障害が出るので安定したV1.6を選択します。
V1.7ではdnfでインストールできるリポジトリがあるのですがV1.6にはありません。~~
しかしそこは心配ご無用、バイナリインストーラーが用意されています。

まずは、https://openlitespeed.org/downloads/ にアクセスしてOpenLiteSpeed V 1.7.xx Stableを探します。
binaryボタンを押下してダウンロード、もしくはWindowsターミナルなどでリモート接続している人はリンクをコピーしてサーバでダウンロードすると良いでしょう。

適当なディレクトリにアーカイブを持っていって解凍します。

解凍したディレクトリに移動して./install.shと入力すると、依存関係のあるパッケージをダウンロードしてインストールしたのちに自分たちを/usr/local/lswsにコピーします。
###インストールの最終段、赤字で管理者パスワードが表示されますので見逃さないように。

<details><summary>初期状態で7080/tcpと8088/tcpを使用しているのでファイアウォールを解放します。ついでに基本のポートも開放しましょう</summary>
```shell-session
[root@localhost openlitespeed]# firewall-cmd --add-port=7080/tcp --permanent
success
[root@localhost openlitespeed]# firewall-cmd --add-port=8088/tcp --permanent
success
[root@localhost openlitespeed]# firewall-cmd --add-service=http --permanent
success
[root@localhost openlitespeed]# firewall-cmd --add-service=https --permanent
success
[root@localhost openlitespeed]# firewall-cmd --reload
success
```
</details>

解放が終わったら早速起動です。
```shell_session
[root@localhost openlitespeed]# /usr/local/lsws/bin/lswsctrl start
[OK] litespeed: pid=8778.
```

ブラウザでアクセスしてみましょう。
https://<サーバのIPアドレス>:7080/
おっと、証明書エラーですねぇ。インストール直後は無効な証明書を使用しているのでどうしようもありません、無視して先に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101752/a73d22ac-6ae2-da78-c319-8eaa0544e890.png)

取りあえず、インストール完了です。
この後はバーチャルホストの設定とphpのインストールがあります。

まず、開発者ツールをインストールします。
```shell_session
# dnf group install 開発ツール
～～～省略～～～
完了しました!
```

ここからコンパイルを始めても良いのですが、オプション選択で必ずエラーになるのであらかじめ必須のライブラリを用意します。
このうち、oniguruma-develはPower-Toolsの有効化が必要になります。
```shell_session
#nano /etc/yum.repos.d/Rocky-PowerTools.repo
#dnf install libxml2-devel openssl-devel sqlite-devel libcurl-devel libpng-devel oniguruma-devel
```
複数の macOS がインストールされた環境へ Windows 10 をインストールして音声を正常に再生する

検証機など、パーティションを分けて複数の macOS（10.13〜10.15）をインストールした環境へ Boot Camp を使用して Windows 10 をインストールする際の覚書です。

※ Apple から EFI 環境向けのオーディオドライバが公開されていないため、単純に EFI boot で Windows 10 をインストールすると音声の再生が行えません。

## TL;DR
先頭パーティションのサイズを macOS + Windows 分確保して Boot Camp を使用すれば OK です。

## パーティションの作成
ディスクユーティリティを起動してパーティションを作成します。

メニューから「表示」→「すべてのデバイスを表示」を選択すると、対象のディスクドライブを選択できるので、この状態で作成します。

インストールする macOS 毎にパーティションを作成します。
![shot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54471/fedf401e-6083-5ffd-6736-27ddc930b225.png)
この際に先頭（円グラフ右上）のパーティションは Windows で使用するディスクサイズを含んだ状態で作成します。

#### 備考
Boot Camp はインストール先パーティションを MBR と互換性のあるパーティションとして Windows に認識させることで、非 EFI 環境でのインストールと OS の起動を実現します。

これはディスク上の先頭パーティションでのみ行なえます（確か MBR 側の制限だった筈）。

## Boot Camp ユーティリティの実行
先頭パーティションへ macOS をインストールしたら、Boot Camp ユーティリティを使用して Windows のインストールを行います。
![bootcamp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54471/08021f4e-ce75-8e5d-c215-8a3ebf587daa.png)
あとは通常通り、Boot Camp ユーティリティで取得したドライバーをインストールすれば作業は完了です。
pygribのインストール

## pygribのインストールでハマったメモ

Dockerfileをこれにしたらいけた

```
FROM gcr.io/deeplearning-platform-release/tf2-cpu.2-3

RUN apt-get update && apt-get -y upgrade
RUN apt-get -y install libgrib-api-dev
RUN apt-get -y install libeccodes-dev
RUN apt-get -y install libmagplus3v5
RUN apt-get -y install libproj-dev
RUN apt-get -y install proj-data
RUN apt-get -y install proj-bin
RUN apt-get -y install gdal-bin
RUN apt-get -y install libgeos-dev
RUN apt-get -y install libssl1.0.0
RUN apt-get -y install libssl-dev

RUN pip install pyproj
RUN pip install eccodes-python
RUN pip install pygrib
RUN pip install ecmwf-api-client
RUN pip install Magics

# 鍵をコピー
COPY keys/.ecmwfapirc /root/.ecmwfapirc
```
MySQLでビューを扱う

###ビューとは
SQLの観点から見ると、テーブルとビューは同じもの。
2つの違いはテーブルの中には実際のデータが保存され、
ビューの中にはselect文が保存されている点。
ビュー自体はデータを持たない。

###ビューを作成する

以下のようなテーブルがある状態。
![スクリーンショット 2020-09-24 16.49.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/ff0bd075-3ac7-3850-2f0c-bba600481af6.png)

create view ~でビューの作成を行う。

````sql
--- whereで条件をつけているがここはもちろん無くても実行可能
create view sumple  as select shohin_mei, hanbai_tanka, torokubi from Shohin where hanbai_tanka >= 1000 and torokubi = '2009-09-20';
````

作成したビューを検索する。
以下のSQLを実行した場合、
1.最初にビューに定義されたselectが実行される。
2.1の結果に対し、ビューをfrom句に指定したselect文が実行される。
ビューに対する検索では2つ以上のselect文が実行される、

````sql
select * from sumple;
````
![スクリーンショット 2020-09-24 16.54.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/7347014c-ee90-86f4-c7ec-ba2fbc89f68d.png)

###ビューを削除する

drop view ビュー名で削除

````sql
drop view sumple;
````


こちらを参考にさせていただきました。
<a href="https://www.amazon.co.jp/dp/B01HD5VWWO/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1">SQL 第2版 ゼロからはじめるデータベース操作
</a>