OmniAICreator/Qiita-1.07M huggingface dataset:
firebase cloudfunctions上のpython関数をローカルでテストする

おそらくgcloudのツールとかを使ってローカルに仮想環境作ったりするのが順当な手順なんだと思うが、めんどくさかったのでflaskの `test_request_context()`を使った。

以下がcloudfunctionsのhello_world関数

```python
def hello_world(request):
    """Responds to any HTTP request.
    Args:
        request (flask.Request): HTTP request object.
    Returns:
        The response text or any set of values that can be turned into a
        Response object using
        `make_response <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>`.
    """
    request_json = request.get_json()
    if request.args and 'message' in request.args:
        return request.args.get('message')
    elif request_json and 'message' in request_json:
        return request_json['message']
    else:
        return f'Hello World!'
```

これを動かすにはこのようにすれば良い

```python
import flask

app = flask.Flask(__name__)

@app.route('/test/')
def hello_world(request):
    """Responds to any HTTP request.
    Args:
        request (flask.Request): HTTP request object.
    Returns:
        The response text or any set of values that can be turned into a
        Response object using
        `make_response <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>`.
    """
    request_json = request.get_json()
    if request.args and 'message' in request.args:
        return request.args.get('message')
    elif request_json and 'message' in request_json:
        return request_json['message']
    else:
        return f'Hello World!'

if __name__ == '__main__':
    with app.test_request_context('/test/'):
        response = hello_world(flask.request)
        print(f'{response}')
    with app.test_request_context('/test?message=hello_hello_how_low?'):
        response = hello_world(flask.request)
        print(f'{response}')
```
C# .csproj に 外部DLL 追加

#はじめに
Visual Studio の Express が 2017 で終わりってことで Visual Studio Code へ移行
C++はQtと組み合わせて なんとなく移行できたことにした
しかし 配布されたSDKが.NETで組まれていたため Qt で組むより .NET でそのまま組んだ方が楽じゃないかなと思い立つ
その思いが甘かった
C++/CLI の特殊な書き方が全く頭に入らずラムダ式より拒否感が強い
この際だから C# を覚えてみようと路線変更するも 外部DLLの追加方法が分からない！
検索すると Visual Studio のIDEを使った追加方法はあるが 直接 .csproj に追加する方法が見つからない！
余りにも簡単すぎて 記事にする必要もないのかもしれないが Qiita にはいつもお世話になりまくっているので 覚書として

#1．プロジェクトを作成
次のコマンドでWindows Form用アプリのプロジェクト(Sample.scproj)を作成

```bat
> mkdir Sample
> cd Sample
> dotnet new winforms
```

#2. Sample.csprojを編集
配布されたSDKがMSILではなかったので プラットフォームを指定する必要あるらしい

```xml:Sample.csproj
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
    <Platform>x64</Platform> <!-- SDKに合わせ Platformを追加 -->
  </PropertyGroup>

  <!-- このItemGroupも追加 -->
  <ItemGroup>
    <Reference Include="Foo.Bar.Baz">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>lib\x64\Foo.Bar.Baz.dll</HintPath>
    </Reference>
  </ItemGroup>

</Project>
```

これで Foo.Bar.Baz のクラスが使用できるようになる
HintPath はプロジェクト下にDLLがあれば記述は不要かも

#3. パッケージの参照
IDEを使っている分には余り意識しなくてもよさげだが dotnet new で生成したプロジェクトだとパッケージ参照エラーになる
SqlClientパッケージを追加した場合は次のコマンドを実行

```bat
> dotnet add package System.Data.SqlClient
```

次の様にプロジェクトファイルにパッケージの参照情報が追記される

```xml:Sample.csproj
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
    <Platform>x64</Platform>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="Foo.Bar.Baz">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>lib\x64\Foo.Bar.Baz.dll</HintPath>
    </Reference>
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
  </ItemGroup>

</Project>
```

#おわりに
前述した通り ご存知の方には それが何？でしょうが 誰かのためになれば幸いです
deviseでUser名などのカラムをDBに保存する方法

## はじめに
deviseはデフォルトだとメールアドレスとパスワードでしかUser情報をDBに保存することができません。
今回はポートフォリオ作成時にアカウント名を保存させたかったのでメモとして残します。

## deviseインストール
```ruby:Gemfile
gem 'devise'
```

```ruby:ターミナル
$ bundle install
```

```ruby:ターミナル
$ rails g devise install
Depending on your application's configuration some manual setup may be required:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

     * Required for all applications. *

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

     * Not required for API-only Applications *

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

     * Not required for API-only Applications *

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

     * Not required *

```

これでインストールはOK

## モデルの作成とカラム追加
今回はUserモデルにaccount_nameというカラムを追加する。

まずはモデルを作成し

```ruby:ターミナル
$ rails g devise User
```

生成されたmigrationファイルに以下を記述しmigrateする

```ruby:20210310005116_devise_create_users
　class DeviseCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      # ==========追加==========
      t.string :account_name, null: false   
      # =======================


      t.timestamps null: false
    end 

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
   end
  end
```

```ruby:ターミナル
$ rails db:migrate
```

## account_nameをDBに保存できるようにする
deviseはデフォルトでメールアドレスとパスワードはパラメータを受け取るようにストロングパラメータが設定されているのでこのパラメータを設定することで保存できるようになります。

deviseでストロングパラメータを設定するには`configure_permitted_parameters`というメソッドを定義する。

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base

  # ==========ここから追加==========
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:account_name])
  end
  # ==========ここまで追加==========

end
```
これで設定完了。

## Viewの作成とaccount_nameのフォームを追加

viewファイルを作成し

```ruby:ターミナル
$ rails g devise:views
```

フォーム部分を追加して完成

```ruby:views/registrations/new.html.erb

 <div class="field">
    <%= f.label :アカウント名 %><br />
    <%= f.text_field :account_name, class: "form-control" %>
 </div>
```
Vue.js始めてみました④(v-on)

この度Vue.jsを学び始めました。
その勉強内容をまとめます。


## v-on

ユーザーがボタンをクリックしたりキーボードから入力したりしたイベントをつないで処理したい時にv-onを使います。

以下が基本的な書き方です。

```JavaScript:Vue.js

<タグ v-on:イベント="メソッド">

//以下のように省略することもできます。
<タグ @イベント="メソッド">

```

## 使い方

例えば`ボタンをクリックした時`という場合は以下のように記述します。

```JavaScript:Vue.js

<button v-on:click="メソッド名"></button>
```

具体的な使い方を以下に記載します。

```JavaScript:Vue.js

//ボタンをクリックしたら数字が1ずつ増える

<div id="app">
  <p>{{ count }}</p>
  <button v-on:click="up">1増える</button>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      count:0
    },
    methods: {
      up: function() {
        this.count++;
      }
    }
  })
</script>
````

上記では

- `el`で`どのHTMLとつなげるか`を指定
- `data`で初期で入れておく`データ`を指定
- `methods`で`どのような処理をするか`を指定

をしています。

`this.count++;`とすることで1ずつ増えていくという処理をすることができます。


以下のように引数を設定することでいろいろな値で増やすこともできます。

```JavaScript:Vue.js

//ボタンをクリックしたら数字がいろいろ増える

<div id="app">
  <p>{{ count }}</p>
  <button v-on:click="up(10)">10増える</button>
  <button v-on:click="up(50)">50増える</button>
  <button v-on:click="up(100)">100増える</button>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      count:0
    },
    methods: {
      up: function(value) {
        this.count += value;
      }
    }
  })
</script>
````

`function(value)`とすることで`v-on:click="up(10)"`の引数である10を受け取り、10増えるという処理になります。


以上です。
OpenAPIのSwaggerからjsonを無理矢理Insomniaにimportする


## 背景
- InsomniaにSwaggerAPIを読み込みたい
- ただし、SwaggerがOpenAPIで提供されているため YAML or JSON　ファイルを出力できない
    - 本来ならexport用のURLが上部に記載されているので、そのURLをInsomniaにimportすれば良い


## 手順

- インストール
  - https://insomnia.rest/download

## 対応策
- Swaggerのページを開く
- F12でChrome Devtoolを開く
- Networkタブを開く
- ブラウザのページを更新する
- swagger-ui-init.jsのResponseを見る
- optionsのcomponentsの範囲をコピー→任意の名前でjsonファイルをローカルに保存

- Insomniaを開く
- import Dataで、先ほど作成したjsonファイルを読み込む。
- Manage Environmentなどを更新
Railsでのアプリケーションの作成手順

本日は、Railsでの開発手順を忘れないように記事に
残したいと思います。

### アプリケーションの雛形を作る

```
rails _6.0.0_ new アプリケーション名 -d mysql
```

・rails newコマンド
Railsで新規アプリケーションを作成する際に使用します。このコマンドを実行することで、
Railsアプリケーションの雛形が作成されます。
6.0.0はバージョンを指定しています。

・-dオプション
rails newコマンドにつけることのできるオプションです。
つけるkotoniyoriデータベースの管理システムの種類を指定できます。

これで、雛形の作成は完了です。

### データベースの作成
雛形はできましたが、情報の保存先であるデータベースが作成されていません。

```
# 作成したアプリのディレクトリにいることを確認
% pwd

# データベースの作成
% rails db:create
```
これで、データベースの作成完了です。
作成前に必ず、ディレクトリを確認しましょう。

雛形の作成は以上となります。
お使いの環境により変わると思うので、このやり方が
全てではありません。
gnuplotで複数のファイルを描画する

# 基本系


```
plot "file1.txt" u 1:2, "file2.txt" u 1:2, "file3.txt" u 1:2
```
`,`で区切る

# ラベリングされている場合

`plot for`を使うと便利。

下記４つは同じ。

```
plot for [i in "1 2 3"] i".txt" u 1:2
```

```
plot for [i=1:3] i".txt" u 1:2
```

```
plot for [i=1:3] sprintf("%d.txt",i) u 1:2
```

```
plot "1.txt" u 1:2, "2.txt" u 1:2, "3.txt" u 1:2
```

# 複雑なファイル名
`sprintf()`関数を使う。
下記二つは同じ

```
plot for [i=50:150:50] sprintf("out_%03d.txt",i) u 1:2 w l t sprintf("%d",i)
```

```
plot out_050.txt u 1:2 w l t 50,  out_100.txt u 1:2 w l t 100,  out_150.txt u 1:2 w l t 150
```
【Salesforce】Apexテストクラス実行時、自動採番は[0000]の4桁でも[100000]の6桁で出力する

# 実現方法

下記の動作でした。

テストクラス実行時

[00] →  100001
[0000] →  100001
[000000] →  100001
[00000000] →  00100001

# 参考リンク

[自動採番項目の表示形式について](https://help.salesforce.com/articleView?id=000315961&type=1&mode=1)

[自動採番項目で欠番が生じる](https://help.salesforce.com/articleView?id=000332666&type=1&mode=1)
Flutterで作ったアプリをAndroidとiOSにadmobをつけて同時にリリースする(時系列順整理)

---
# :book: Flutterの記事を整理し本にしました :book:
https://zenn.dev/kazutxt/books/flutter_practice_introduction

* <font color="red"><b>本稿の記事を含む様々な記事を体系的に整理し本にまとめました</b></font>
* 今後はこちらを最新化するため、<font color="red"><b>最新情報はこちらをご確認くださ</b>い</font>
* 10万文字を超える超大作になっています(笑)

---

# はじめに
## この記事について
* flutter系の記事としてカテゴリ別に以下の記事を執筆したのですが、実際に使うときは横断的に開発順に行う必要があり、少しわかりにくいので、時系列順にならべて、何を行うかを整理しました
    * androidの記事:
[Flutterで作ったアプリをAndroidとiOSとWebに同時にリリースする(Android編)](https://qiita.com/kazutxt/items/66d52d78ec1349f2b249)
    * iOSの記事 : [Flutterで作ったアプリをAndroidとiOSとWebに同時にリリースする(iOS編)]
(https://qiita.com/kazutxt/items/0ea523d5ccf647c144ad)
    * admobの記事:[flutterでアプリ公開してからadmob導入するまで](https://qiita.com/kazutxt/items/4f8f802aa7232f922346)

### 前提
* Flutterを使った、AndroidとiOSの同時リリース
* admobもつける

# 本編
## 開発を始めるときにやること

1. コンセプト/プロジェクト名を決める
2. Flutter new projectでプロジェクトを作る
3. Githubにリポジトリを作成し、初期コミット&push
4. アプリ名の設定
    * androidの記事:項番5,iOSの記事:の項番5
5. bundleID,profileを作成する
    * iOSの記事:の項番3,4
6. Firebaseにプロジェクトを作成する
    * admobの記事:項番2
7. Androidのビルド準備
    * androidの記事:項番4,5,6
8. admob関連
    * admobの記事:項番1,2


ビルドして動作確認(デフォルトのアプリができること)して、push

## 開発
* admobのIDをテスト用にする
    * admobの記事：項番3
* 楽しくコーディング

## 開発が終わってからリリース時にやること

1. スクリーンショットを取る
    * サイズや解像度種類に注意
2. アイコンの設定
    * GooglePlayようにフィーチャーグラフィックという横長アイコンも準備する
3. サポートサイト&プライバシーポリシーの作成
    * iOSの記事:の項番8
4. GooglePlayのアプリ作成&リリース作成&資材アップロード
    * androidの記事:項番7,8,9
5. AppStoreのアプリ作成とリリース作成＆資材アップロード
    * iOSの記事:の項番6,7,9

## 備考
* プロジェクト名はできれば英数字にできればよい
    * Andorid/Firebase系では、`-`が使えないので、`_`を使うことになる
    * iso系では`_`が使えないので、`-`をつかう
ThreeTenABPのLocalDateTimeをUNIXタイムスタンプに変換する

`ThreeTenABP`の`LocalDateTime`をUNIXタイムスタンプに変換する方法です。

今回はJST（日本標準時）に変換したいと思います。

事前準備として「ライブラリの追加・ThreeTenABPの初期化・現在日時の取得」を行います。

```app/build.gradle
implementation 'com.jakewharton.threetenabp:threetenabp:1.3.0'
```

```MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
	
        // 初期化
        AndroidThreeTen.init(this)
        // 現在のLocalDateTimeを取得
        val nowDateTime = LocalDateTime.now()
}
```

# ZoneOffset#ofHours
`ZoneOffset#ofHours`は、UTCからの時差を指定します。
UTCとJSTの時差は「9時間」で、UTCが「09:00」のときJSTは「18:00」となるので、9時間加算します。

```kotlin
nowDateTime.toEpochSecond(ZoneOffset.ofHours(9))
nowDateTime.toEpochSecond(ZoneOffset.ofHours(+9))
```

ちなみにOffsetとは「ある基準点からの距離を表した値」という意味で、ここでは「基準点->UTC」で「距離->時差」ということですね。

# ZoneId#of
`ZoneId#of`は、タイムゾーンIDを文字列で渡して、返された`ZoneId`からタイムスタンプを取得します。

以下のように、複数パターンの文字列を渡すことが出来ます。

```kotlin
nowDateTime.atZone(ZoneId.of("UTC+09:00")).toEpochSecond()
nowDateTime.atZone(ZoneId.of("UTC+09")).toEpochSecond()
nowDateTime.atZone(ZoneId.of("UTC+9")).toEpochSecond()
nowDateTime.atZone(ZoneId.of("UT+09:00")).toEpochSecond()
```

# まとめ
ThreeTenABP便利〜。
MediaStoreの「DATE_TAKEN」「DATE_ADDED」について

`MediaStore.Images.Media.DATE_TAKEN`カラムと、`MediaStore.Images.Media.DATE_ADDED`カラムのタイムスタンプについて勘違いしていたので、まとめておきたいと思います。

# 「DATE_TAKEN」はミリ秒、「DATE_ADDED」は秒

`UNIXエポック（1970年1月1日午前0時0分0秒（UTC））`を基準に、`DATE_TAKEN`は経過日数をミリ秒で、`DATE_ADDED`は秒で表したタイムスタンプを持っています。

`DATE_TAKEN`と`DATE_ADDED`のタイムスタンプは、以下のようになっています

## DATE_TAKEN
- 1111295661000

## DATE_ADDED
- 1602652291

`DATE_TAKEN`は、`Android 10（Android Q/API Level 29）`から追加されたカラムなので、使用するときは以下のような判定が必要です。

```kotlin
val column = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
  MediaStore.Images.Media.DATE_TAKEN
} else {
  MediaStore.Images.Media.DATE_ADDED
}
```

# タイムスタンプに関する単語について

よく理解していない単語もあったので、まとめておきたいと思います。

## UTC
- Coordinated Universal Timeの略
- 協定世界時のこと
- 世界標準で使われている時間
- 日本（JST/日本標準時）との時差は「9時間」で、UTCが「09:00」なら日本は「18:00」になる

## UNIXタイムスタンプ
- 1970年1月1日午前0時0分0秒を基準にして、経過日数を秒で表したもの

## UNIXエポック
- 1970年1月1日午前0時0分0秒のこと

# 日時を指定して端末に保存されている写真を取得する

特定の日時以降に撮影された写真のURIを取得する実装です。日時の取り扱いには`ThreeTenABP`ライブラリを使用しています。

```app/build.gradle
implementation 'com.jakewharton.threetenabp:threetenabp:1.3.0'
```

```kotlin
fun loadTakenPhotoUris(context: Context, dateTime: LocalDateTime): List<Uri> {

        val uris = mutableListOf<Uri>()

        // 取得したいカラムを指定する
        val projection: Array<String> = arrayOf(MediaStore.Images.Media._ID)
        // 検索条件:特定の日時以降に保存された画像を取得する
        val selection = "${MediaStore.Images.Media.DATE_ADDED} >= ?"
        val timestamp = toTimestamp(dateTime).toString()
        // selectionの「?」に入る値
        val selectionArgs: Array<String> = arrayOf(timestamp)
        // DATE_ADDEDで昇順にする
        val sortOrder = "${MediaStore.Images.Media.DATE_ADDED} ASC"

        context.contentResolver.query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            projection,
            selection,
            selectionArgs,
            sortOrder
        ).use { cursor ->

            cursor ?: return@use

            val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)

            while (cursor.moveToNext()) {

                val imageId = cursor.getLong(columnIndex)

                val uri = Uri.withAppendedPath(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    imageId.toString()
                )

                uris.add(uri)
            }
        }

        return uris
    }

    private fun toTimestamp(dateTime: LocalDateTime): Long {
        // JSTに変換
        val zonedDateTime = dateTime.atZone(ZoneId.of("UTC+09:00"))
        return zonedDateTime.toEpochSecond()
    }
```
MediaStore.queryで端末の画像が取得出来ない...?

`MediaStore#query`で端末の画像を取得しようとしたんですが、なぜかアプリで撮影・保存した画像しか取得出来ませんでした。

うーん、なぜだ...わからぬ。

ということで地味にハマったので、ここに記す。

# 「READ_EXTERNAL_STORAGE」パーミッションのチェックを行う
`MediaStore#query`で画像を取得する前に、`READ_EXTERNAL_STORAGE`パーミッションのチェック・許可をしていなかったので、取得出来なかっただけでした...（笑）

なんてこったパンナコッタ。

# 端末の画像一覧を取得する方法
```AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="...">
    // パーミッションを設定
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
```
```MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // 端末の画像を取得する
    loadImages()
}

// requestPermissionsの後に呼び出される
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)

    if (requestCode != REQUEST_CODE_PERMISSION) return

    if (grantResults.isNotEmpty() && (grantResults.first() == PackageManager.PERMISSION_GRANTED)) {
        // 許可した後の処理
    }
}
    
private fun loadImages() {

    // READ_EXTERNAL_STORAGEパーミッションが許可されているかチェックする
    val isGranted = ContextCompat.checkSelfPermission(
        this,
        Manifest.permission.READ_EXTERNAL_STORAGE
    ) == PackageManager.PERMISSION_GRANTED

    // 許可されていない場合、パーミッションの許可を選択するダイアログを表示する
    if (!isGranted) {
        requestPermissions(
            arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
            REQUEST_CODE_PERMISSION
        )
        return
    }

    val uris = mutableListOf<Uri>()

    // 外部ストレージを指定する
    val queryUri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI

    // queryで取得したいカラムを指定する
    val projection: Array<String> = arrayOf(MediaStore.Images.Media._ID)

    /**
     * 検索条件を指定する。
     * 条件は「"${MediaStore.Images.Media.DATE_TAKEN} >= ?"」のように記述する。
     * 全件取得のときはnullを指定する。
     */
    val selection: String? = null

    /**
     * selectionの「?」に代入する条件を指定する。
     * 全件取得のときはnullを指定する。
     */
    val selectionArgs: Array<String>? = null

    /**
     * ソート条件を指定する。
     * 条件は「"${MediaStore.Images.Media.DATE_ADDED} DESC"」のように記述する。
     * 条件を指定しない場合はnullを設定する。
     */
    val sortOrder: String? = null

    contentResolver.query(
        queryUri,
        projection,
        selection,
        selectionArgs,
        sortOrder
     ).use { cursor ->

        cursor ?: return@use

        // projectionで指定していないカラムを取得しようとすると、例外がスローされる。
        val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)

        while (cursor.moveToNext()) {

            val imageId = cursor.getLong(columnIndex)
	　　　
            // メディアアイテムのURIを取得する
            val uri = Uri.withAppendedPath(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                imageId.toString()
            )

            uris.add(uri.toString())
        }
    }
}
```
FusedLocationProviderClientのLastLocationがnullになる

`FusedLocationProviderClient`の`LastLocation`が`null`になってしまう現象に遭遇したので、原因と解決方法を書きたいと思います。

# nullのときは`requestLocationUpdates`
`LastLocation`が`null`のときは`fusedLocationProviderClient.requestLocationUpdates()`を呼び出して、位置情報を取得します。

```kotlin

val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)

fusedLocationProviderClient.lastLocation.addOnSuccessListener { location: Location? ->
            
　　location ?: run {
　　　　val request = LocationRequest.create().apply {
　　　　　　interval = 5000
          fastestInterval = 3000
          priority = LocationRequest.PRIORITY_HIGH_ACCURACY
    　　}
       fusedLocationProviderClient.requestLocationUpdates(
　　　　　　request,
          object : LocationCallback() {
          　　override fun onLocationResult(result: LocationResult) {
　　　　　　　　　　super.onLocationResult(result)

　　　　　　　　　　val lastLocation = result.lastLocation
	  
	  　　　　// 何か処理を行う
　　　　　　　　　　_current = LatLng(lastLocation.latitude, lastLocation.longitude)
	  
　　　　　　　　　　// 一度だけ位置情報が取得出来ればいいので、取得後は位置情報の更新を停止する。
　　　　　　　　　　fusedLocationProviderClient.removeLocationUpdates(this)
              }
          }, Looper.getMainLooper())
　　}
}
```

# なぜnullになるのか？
再起動後など**端末が一度も位置情報を取得していない**ときに発生します。
なので、GoogleMapを起動して位置情報を取得すると、`LastLocation`がちゃんと返ってくるようになります。

# まとめ
端末を再起動したことを忘れて「あれ...？なんでnullになるんだ...」とハマってしまうことがよくあったので、今回書いてみました（笑）

誰かのお役に立てれば幸いです٩( 'ω' )و
Laravelで○日前を取得したい。

下記のようにすればとりあえずは実現可能。

まずはモデルにコードを書く。

```php:App\Models\Article.php

<?php

//省略

class Article extends Model
{

    //省略

    public function getDiffDate()
    {
        // 最終更新日
        $updated_date = new \Carbon\Carbon($this->updated_at);
        // 現在の日付
        $now = \Carbon\Carbon::now();
        //差分
        $diff = $updated_date->diff($now);

        if ($diff->y == 0 && $diff->m == 0 && $diff->d === 0 && $diff->h === 0 && $diff->i === 0) {
            return $diff->s.'秒前';
        } elseif ($diff->y == 0 && $diff->m == 0 &&$diff->d === 0 && $diff->h === 0) {
            return $diff->i.'分前';
        } elseif ($diff->y == 0 && $diff->m == 0 && $diff->d === 0) {
            return $diff->h.'時間前';
        } elseif ($diff->y == 0 && $diff->m == 0) {
            return $diff->d.'日前';
        } elseif ($diff->y == 0) {
            return $diff->m.'ヶ月前';
        } else {
            return $diff->y.'年前';
        }
    }
}

```

あとは呼び出す。

```php:test.blade.php
{{$article->getDiffDate()}}
```

簡単。


もっと良い方法あれば教えてくださいm(_ _)m
Kotlin MultiPlatform Mobile(KMM)の環境構築 for Mac

Kotlin MultiPlatform Mobileがアルファ版に進んだようなので、ちょっと触ってみようと思い立って環境構築してみました。
色々とハマって3日くらいかかりましたがなんとかできたので、ナレッジ共有と備忘録も兼ねて残しておきます。

# What's KMM？
モバイルマルチプラットフォームを実現するKotlinベースの開発キットです。
Android - iOS間のビジネスロジックの再利用ができる点が魅力で、Androidアプリ開発後、iOSアプリも必要になったときや、最初から両方のアプリを作る予定ならすごく便利なんじゃないかなと思ってます。

https://kotlinlang.org/lp/mobile/

Flutterとよく比較されますが、Flutterがビュー側も含めたプラットフォーム共有なのに対し、KMMはビジネスロジックのみをシングルコードにするので、ビュー側はプラットフォーム特有のものにできる点が異なります。

# 環境構築する

公式チュートリアルを参考にしてます。
https://kotlinlang.org/docs/mobile/setup.html

今回は↓の環境で構築しました。
 - MacOS 10.14.6
 - XCode 11.3.1 ←11.3以上必須

## Android Studio4.2をインストール
現時点(2021/03/10)での安定板は4.1.2なので、ベータ版を使う必要があります。
↓からver4.2をダウンロードしてインストールします。
https://developer.android.com/studio/preview?hl=ja

## Kotlinのアップデート
Android Studioで適当に1つプロジェクトを作成した後、[Tools]→[Kotlin]→[Configure Kotlin Plugin Updates]と進み、最新バージョンにアップデートします（僕の場合はプラグインバージョン[202-1.4.31-release-AS8194.7]が入っていて、更新の必要なかったです）。

## Kotlin MultiPlatform Mobile Pluginをインストール
[Preferences]→[Plugins]と進み、検索ボックスにKotlin Multiplatform Mobileと入力します。
![設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351306/06cf46b9-5c6c-6770-9fc8-0be93fb8585a.png)

## Android 10.0をインストールする
公式サイトにはないんですが、僕の環境だとこれをしないとビルドがうまく通らなかったです。
Android SDK画面からAndroid 10.0をインストールしておきましょう。
ここまでやったら一度Android Studioを再起動します。

## KMMプロジェクトを作成する
プロジェクトの新規作成画面に「KMM Application」が追加されているはずなので、選択します。
![新規プロジェクトの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351306/b29372ca-f094-d297-7d17-88503430553c.png)

アプリケーションのNameを変えて次へ
![新規プロジェクトの作成_と_MyApplication_–_Greeting_kt__MyApplication_shared_commonMain_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351306/0898e2a8-2732-fa9c-f313-44b93d20adda.png)

最後に各プラットフォームのアプリケーションの名前を入力します。
Shared Module NameはAndroidとiOSの共有モジュール名です。デフォルトで大丈夫です。
最後にAdd sample tests for Shared Moduleにチェックを付けて完了します。
![新規プロジェクトの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351306/67358b19-a18a-d006-e77e-e0ffdf117a94.png)

KMMアプリケーションが作成されるので、ビルドされるまで待ちます(僕の場合は5分くらいかかりました)。
あと、デフォルトではエクスプローラーにはAndroidしかありませんが、ここでプロジェクトに変えるとiOSも出てきます。変えておきましょう。
![MyApplication_と_「Kotlin_MultiPlatform_Mobile_KMM_の環境構築_for_Mac」を編集_-_Qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351306/7131250a-f096-75b2-4537-d0798e66b07d.png)

## アプリを実行する

Androidならこう
![MyApplication.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351306/644e5cce-fc53-6506-9ad2-a22d72330557.png)

iOSならこうでエミュレーターが起動します。
![MyApplication.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351306/a2dd1c61-ceb7-31d9-6baa-0e4d0b7302ae.png)
VSCodeでLive Sass Compilerが動作しないときの対処法

#エラー内容と原因
この画面がVSCodeの右下に出てきて、Emmetも改行すらも効かなくなるということが発生しました。
各種プラグインの再インストール、VSCodeの再インストールを行った結果、Sass系のプラグインが原因でした。
![]()
<img width="80%" alt="vscode_error.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635867/1bd165d7-6d45-43b0-6bee-e283d4a5320c.png">

#使用環境
・MacBook Air (2019)
・macOS Big Sur 11.2.1
・VSCode 最新版

#エラー解決方法
ネットで調べていると、原因となりそうな事象が２つほどあるみたいです。

**【原因】**
**1. Live Sass Compilerのバージョンが古い**
**2. HTMLHintというプラグインを導入している**

このどちらかが原因の場合が多いみたいです。

**【解決方法】**
**1.まずは自分が使っているLive Sass Compilerのバージョンを確認しましょう。**
<img width="80%" alt="スクリーンショット 2021-03-11 8.54.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635867/0cb806ae-c637-aff2-1361-bfcfae367cb7.png">
VSCodeのプラグインを検索したときに出るLive Sass Compilerのバージョンを**3.0.0ではなく、4.X.Xをインストールしましょう**。

**2.HTMLHintをアンインストールしましょう**

<img width="80%" alt="スクリーンショット 2021-03-11 9.17.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635867/2b977977-ddc4-f08d-61bd-e491b8505153.png">


このプラグインがSass系のプラグインと相性が悪いことがあるみたいです。
もし4.X.Xをインストールしてもエラーが出るようなら、アンインストールしてみてください。

自分は4.X.Xをインストールしたら他のプラグインも問題なく動作し、エラーが解決しました。
ちなみに3.0.0は2018年あたりで更新が止まっているみたいで、最新のVSCodeではエラーが出ることが多いらしいです。

ほとんどこれで改善されると思いますが、万が一解決しない場合は、プラグインの再インストールとVSCodeの再インストールをしてみることもおすすめします。
そのやり方も参考URLに記載しておきます。

##参考URL
・VSCodeのアンインストール方法
https://daeudaeu.com/visual-studio-code-%E3%81%AE-mac-%E3%81%8B%E3%82%89%E3%81%AE%E3%82%A2%E3%83%B3%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/
jupyter notebookの使い方の超簡単な解説記事　no.2

こんにちは、まゆみです。

今回の記事では、jupyter notebookの使い方についてお伝えしていこうと思います。

この記事を読めば

><ul>
><li>jupyter notebookのセルのタイプの切り替え方</li>
><li>jupyter notebookでよく使うショートカットキーについて</li>
></ul>

が分かります。

では、さっそく始めていきますね。

#jupyter notebookの大きな特徴は『セル』

jupyter notebookが他のテキストエディタと違う大きな特徴の１つに、

<ul>
<li>セルで区切られていること</li>
<li>セルの中に書くものに応じて、セルには色んなタイプがあること</li>
</ul>

があります。


##jupyter notebookにはどんな種類のセルがあるの？

今あなたがどのようなタイプのセルに入力しているのか知るには、下記のスクショの赤で囲まれた部分を見ると分かります
![スクリーンショット 2021-03-11 073123.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/7cd74003-f567-e491-cf40-2da2b310492f.jpeg)

###Code

『Code』は<font color="Red">python のコード</font>を書くモードのことです。(計算をしたり関数を実行させたりできます)

###Markdown

Markdownに指定をすることで、<font color="Red">テキスト</font>を書くことができます。

テキストとして認識されるので、例えばセルに『3 + 4』と入力しても、『7』とは表示されず、そのまま『3 + 4』と表示されます。

##キーボード上で、セルのタイプを変更したい時

![見出しを追加 (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/69be9a45-8f96-b54d-3fc6-466e0ab6bdfb.png)


マウスで『Code』や『Markdown』を指定せず、キーボードで文字を打つショートカットによって、セルのタイプを変更したい場合は

>ESC キーを押した後、Yを押すと　Codeが書けるモードになり、
>ESC キーを押した後、Mを押すと　テキストが書けるモードに変わります

#jupyter notebookに書いたコードの実行の仕方

jupyter notebook のセルのタイプを『Code』にしてpythonのコードを書いた後

<ul>
<li>Ctrl + Enterで実行すると、<font color="Red">今のセルから移動せずに</font>コードが実行される</li>
<li>Shift + Enterで実行すると、<font color="Red">１つ下のセルに移動して</font>コードが実行される</li>
<li>同じセル内に複数行コードを書くと、Outputとして表示されるのは最後のコードの結果のみ</li>
</ul>

![スクリーンショット 2021-03-11 081623.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/8c345a2e-8ffc-2a87-3d05-672d568e51b6.jpeg)


#jupyter notebook のショートカットについて

![見出しを追加 (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/abe29968-bd68-1f3e-7259-77efb542430b.png)

では次にjupyter notebook で使えるショートカットキーを紹介します。

ショートカットキーを使うには

<font color="Red">ESCキーを押して、まずコマンドモードに切り替える</font>

ことを忘れないでくださいね。


##どんなショートカットキーがあるかの一覧を見たい

ショートカットキー一覧を見たい時は

Help の『H』です。

##新しいセルを一段『下』に作りたい

下を表すBelow の『B』で今あるセルの一段下に新しいセルを作ることができます

##新しいセルを一段『上』に作りたい

上を表すAbove の『A』を押せば今あるセルの一段上に新しいセルを作ることができます

##セルを削除したい

削除を表すDelete の『D』を2回押してください。

2回連続で押すことに注意です。


#まとめ

今回の記事では、jupyter notebook の使い方について簡単に説明させていただきました。

[前回に書いた記事](https://qiita.com/Mayumi_Pythonista/items/3fb668a88576ac6741d5)と合わせて目を通してくだされば、Anaconda を使ってjupyter notebookを開いたり閉じたりすることも合わせて理解できると思います。

よろしくお願いします！
Next.jsにFont Awesomeを導入する手順


Next.jsでFont Awesomeを導入する手順になります。

## Font Awesomeをインストール

### yarnの場合
```
yarn add @fortawesome/fontawesome-svg-core 
　　　　　@fortawesome/free-solid-svg-icons 
　　　　　@fortawesome/free-brands-svg-icons
　　　　　@fortawesome/react-fontawesome
```

### npmの場合
```
npm i --save @fortawesome/fontawesome-svg-core
             @fortawesome/free-solid-svg-icons
             @fortawesome/free-brands-svg-icons
             @fortawesome/react-fontawesome
```

## Font Awesomeを使用したいcomponentsで読み込む

```tsx
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faRss } from '@fortawesome/free-solid-svg-icons'
import { faTwitter } from '@fortawesome/free-brands-svg-icons'
import { faInstagram } from '@fortawesome/free-brands-svg-icons'

export default () => {
  return (
    <div>
      <FontAwesomeIcon icon={faRss} />
      <FontAwesomeIcon icon={faTwitter} />
      <FontAwesomeIcon icon={faInstagram} />
    </div>
  )
}
```

上記のように、Font Awesomeを読み込むことでcomponentsで使用可能です。
@firebase/firestore: Firestore (8.2.9): Could not reach Cloud Firestore backend.を解消する

先日firebaseとreactを接続するところでハマってしまったので
同じ境遇に会ったらぜひ参考にしていただきたいです！

#接続がうまくいかなかった原因
結論必要な記載が漏れていた
【エラー文】

```
@firebase/firestore: Firestore (8.2.9): Could not reach Cloud Firestore backend. Connection failed 1 times. Most recent error: FirebaseError: [code=permission-denied]: Permission denied on resource project "clone3411",.
This typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend
```

最初は接続環境が悪いのかなと思い、そのような記事がたくさんあり何度もwifiをつけ外ししてたがうまくいかず。。。
エラー文をよくみると`clone3411`とに接続がうまくいってないと記載があった！
firebaseconfigファイルが悪いのではと考えfirebaseの設定の箇所を再度コピーしてみた

```firebase.js
  var firebaseConfig = {
    apiKey: "******",
    authDomain: "****",
    projectId: "****",
    storageBucket: "*****",
    messagingSenderId: "*****",
    appId: "****",
    measurementId: "*****"
  };
  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
  firebase.analytics();
```

そのままコピーしてるはずだからうまくいくはず。。。
まだエラー文は直らない。どうしてだろう。。。

#解決方法
調べていくと今のfirebaseConfigには1行足りないコードがあります！
それは`databaseURL:"****"`です！
この記述は自分で記載する必要があり（何故なのかわかりません）それを記述することでエラー文がなくなりました！
URLを書くときは、`databaseURL:"https://projectId（記載のID）.firebaseio.com"`を書く必要があります！

ぜひ同じような現象が起きたときはconfigファイルを見てみるといいかなと思います！
既存プロジェクトを Flutter2.0 向けにアップデート対応してみた

さて、Flutter2.0 がリリースされましたね。

[Flutter 2.0.0 release notes - Flutter](https://flutter.dev/docs/development/tools/sdk/release-notes/release-notes-2.0.0)

そこで既存の Flutter のプロジェクトにて、Flutter2.0 向けにアップデート対応をしましたので、備忘録として手順をまとめておきます。

# 手順

## Flutter および各パッケージのバージョンアップ

ターミナル等でプロジェクトのルートに移動し、下記の 3 つのコマンドを実行します。

```
cd [プロジェクトのパス]
flutter pub upgrade
flutter pub outdated
flutter pub upgrade --major-versions
```

これにより、Flutter のアップデートおよびプロジェクト内で使用しているパッケージのバージョンも更新されます（`pubspec.yaml`が自動的に書き変わります）。
ですが、私の環境では`flutter pub upgrade`コマンドを実行した際、下記のようなエラーが出ました。

```
flutter pub upgrade
Resolving dependencies...
Because god_voice_flutter depends on flutter_localizations any from sdk which depends on intl 0.17.0, intl 0.17.0 is required.
So, because god_voice_flutter depends on intl ^0.16.1, version solving failed.
pub finished with exit code 1
```

この場合、エラー文通りに`intl`のバージョンを修正し、`flutter pub get`コマンドを実行すれば大丈夫です。

```yaml:pubspec.yaml
dependencies:
  intl: ^0.17.0
```

## Web でビルドするための設定を行う

ターミナル等でプロジェクトのルートに移動し、下記の 2 つのコマンドを実行します。

```
cd [プロジェクトのパス]
flutter config --enable-web
flutter create --org [アプリのパッケージ名] .
```

1 つ目のコマンドで Web 版への対応を有効にし、2 つ目のコマンドでプロジェクトを再構築します。
これにより、`main.dart`および、web フォルダとその配下にファイル群が生成されます。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/ee1433c2-a4af-33bd-efb3-c9e7b8697073.png)

アプリを実行する際、デバイスとして Chrome（web）が選べるようになるはずです。

# まとめ

既存プロジェクトを Flutter2.0 向けにアップデート対応してみました。
対応自体は基本的にコマンドを実行していくだけなので、さほど難しくはなかったです。
ただ、既存プロジェクトですとだいぶ影響が大きい（使用しているパッケージが Web に対応していないなど）ため、初期段階で早めに対応すると良さそうです。

# 参考 URL

- [Upgrading Flutter - Flutter](https://flutter.dev/docs/development/tools/sdk/upgrading)
- [既存プロジェクトの Flutter Web 適応 & Firebase Hosting 公開 - Qiita](https://qiita.com/kogepan159/items/9911cf7be67012cf4956)
- [android - Flutter web create issue in existing flutter app - Stack Overflow](https://stackoverflow.com/questions/57992350/flutter-web-create-issue-in-existing-flutter-app)
【rails, Validation】開始日と終了日の逆転防止

# やりたいこと

タスク管理アプリでタスクに登録できる「開始日」と「終了日」が逆転しないようにValidationをかけたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953011/71d8c1c4-a10d-44d4-e8f3-32a5ec290d2b.png)


# 方法
思っていた以上に簡単に実装できました！！

・Step①: モデルにValidationを作成
・Step②: エラーメッセージの日本語化

## Step①: モデルにValidationを作成 
```ruby:app/models/task.rb

class Task < ApplicationRecord
　　　　　：
  validate :start_end_check

  def start_end_check
    errors.add(:end_date, "は開始日より前の日付は登録できません。") unless
    self.start_date < self.end_date 
    end
 end
```

#### ＜実際の画面＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953011/419dbb1e-715d-6645-b4e5-8a8233b6fe6d.png)
できた！！！！！
けれど、文章に違和感。

## Step②: エラーメッセージの日本語化

このままだと「End Dateは開始日より前の日付で登録できません」とルー語も甚だしいので、
日本語化しました(ここでは詳細は省きますが、ja.ymlファイルに以下のように記述。)

```yml:config/locales/ja.yml
---
ja:
  activerecord:
         :
      task:
        task_title: "タイトル"
        start_date: "開始日"
        end_date: "終了日"
        :
```

#### ＜実際の画面＞
![](https://storage.googleapis.com/zenn-user-upload/anq0iaq9vm2ioxaml2gnv445jhqz)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953011/85f9c1d6-f802-fbcf-e6b2-11a8fbb2142a.png)

やりたかったことができました！！
良い感じです。

# errors.add について

しっかり公式も確認しておきます。
[Railsガイド：Active Record バリデーション](https://railsguides.jp/active_record_validations.html#errors-ad)

### errors.add

> addメソッドを使って、特定の属性に関連するエラーメッセージを手動で追加できます。このメソッドは属性とエラーメッセージを引数として受け取ります。

### errors.full_messages
> errors.full_messages（または同等のerrors.to_a）メソッドは、エラーメッセージをユーザーが読みやすい形式で返します。以下のように、メッセージごとに頭が大文字の属性名を冒頭に追加します。

```ruby
errors.add(:属性名, "エラーメッセージ")
```
となっていて、errors.full_messagesで呼び出せる。
このとき、メッセージの冒頭には先頭大文字の属性名が追加される。

# まとめ

基本的にはrailsが自動で作成してくれるものを使用していたので、errors.addでメッセージを手動で作るやりかたを初めて知りました！
まだまだ知らないことがたくさん⋯日々精進します！

# ちなみに⋯
またしても、エラー文で表示が崩れてしまいました。
しかし、1度対処しているので冷静に解決することができました！

エラー文表示のレイアウト崩れについても記事にしておりますので、同じような現象が起こってしまった方はぜひこちらも参照いただけますと幸いです^^

https://qiita.com/ganbareru_ya_uj/items/ab38f7d72a838101f510

# 参考

https://qiita.com/nip0p0/items/b2ee87e416dfbcf27239

https://railsguides.jp/active_record_validations.html#errors-ad
MySQL基礎（サブクエリ）

#COUNT, 関数
```
SELECT COUNT(likes) FROM posts;
SELECT COUNT(*) FROM posts;
```
1. postsテーブルの中のlikesを数を表示
1. postsテーブルの中の全ての数を表示（NULLも含む）

```
SELECT SUM(likes) FROM posts;
SELECT AVG(likes) FROM posts;
SELECT MAX(likes) FROM posts;
SELECT MIN(likes) FROM posts;
```
1. postsテーブルの中のlikesの合計を表示
1. postsテーブルの中のlikesの平均を表示
1. postsテーブルの中のlikesの最大を表示
1. postsテーブルの中のlikesの最小を表示

#GROUP BY
```
SELECT DISTINCT area FROM posts;
SELECT area, SUM(likes) FROM posts GROUP BY area;
```
1. postsテーブルの中のareaを表示（重複しないもの）
1. postsテーブルの中でareaごとのlikeの合計表示

#IF, CASE
```
SELECT 
  *,
  IF(likes > 10, 'A', 'B') AS team
FROM 
  posts;

SELECT 
  *,
  CASE
    WHEN likes > 10 THEN 'A'
    WHEN likes > 5 THEN 'B'
    ELSE 'C'
  END AS team
FROM
 posts; 
```
1. postsテーブルの中のlikesが10より大きい場合はAそれ以外はB
1. postsテーブルの中でlikeが10より大きい場合はA,5より大きい場合はB,それ以外はC

#CREATE　TABLE
```
DROP TABLE IF EXISTS posts_tokyo;
CREATE TABLE posts_tokyo AS SELECT * FROM posts WHERE area = 'Tokyo';

DROP TABLE IF EXISTS posts_copy;
CREATE TABLE posts_copy AS SELECT * FROM posts;

DROP TABLE IF EXISTS posts_skeleton;
CREATE TABLE posts_skeleton LIKE posts;
```
DROP TABLE IF EXISTS〜テーブルがあったら削除する

1. postsテーブルの参照しareaがTokyoのみのposts_tokyoテーブルを作る
1. postsテーブルの参照しposts_copyテーブルを作る
1. postsテーブルの参照し中が空のposts_skeletonテーブルを作る

#サブクエリ
```
SELECT
  *,
  (SELECT AVG (likes) FROM posts) AS avg
FROM
  posts;
```
**AVGは使用する際は全てのレコードをまとめてるためサブクエリを使用する**
1. postsテーブルの中を全て表示かつlikesの平均を出す方法


##補足
GROUP　BYを使用する場合はWHEREが先に実行されるので先にWHEREを書くこと
もし、GROUP　BYしたもので条件を選択したい場合は、HAVINGを使うこと
Windows10 Hone Insider Preview ビルド21327でGPUが使えない

#1.概要

* Windows10 Hone Insider Preview ビルド21327にアップデート後，DockerからGPUを使用するnvidia-dockerイメージを起動できなくなりました（/dev/dxg: no such file or directory）．
* [Cannot use GPU support in Windows 10 preview build 21327](https://github.com/microsoft/WSL/issues/6617)で公式課題として対策されていて，ビルド21332で修正されました．
* Windows Updateでビルド21327→ビルド21332へ更新し，無事起動できるようになりました．

#2.使用環境

##2-1.問題が起きた状況

* docker run実行時のエラーメッセージ

```
$ docker run --gpus all -it --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 nvcr.io/nvidia/tensorflow:20.07-tf1-py3
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: process_linux.go:459: container init caused: Running hook #0:: error running hook: exit status 1, stdout: , stderr: nvidia-container-cli: detection error: stat failed: /dev/dxg: no such file or directory: unknown.
ERRO[0001] error waiting for container: context canceled
```

* WSLカーネルバージョン

```
> wsl --status
既定の配布: Ubuntu-20.04
既定のバージョン: 2

Linux 用 Windows サブシステムの最終更新日: 2021/03/11
Windows Subsystem for Linux カーネルは、' wsl--update ' を使用して手動で更新できますが、システム設定が原因で自動更新が発生することはありません。
カーネルの自動更新を受け取るには、 Windows Update の設定を有効にしてください:' Windowsの更新に、その他のMicrosoftの製品の更新情報を受け取る'。
詳細については、 https://aka.ms/wsl2kernel.
 を参照してください
カーネル バージョン: 5.4.91
```

##2-2.ビルド21332へのアップデート後
```
$ docker run --gpus all -it --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 nvcr.io/nvidia/tensorflow:20.07-tf1-py3

================
== TensorFlow ==
================

NVIDIA Release 20.07-tf1 (build 14714473.1)
TensorFlow Version 1.15.3

Container image Copyright (c) 2020, NVIDIA CORPORATION.  All rights reserved.
Copyright 2017-2020 The TensorFlow Authors.  All rights reserved.

NVIDIA Deep Learning Profiler (dlprof) Copyright (c) 2020, NVIDIA CORPORATION.  All rights reserved.

Various files include modifications (c) NVIDIA CORPORATION.  All rights reserved.
NVIDIA modifications are covered by the license terms that apply to the underlying project or file.

WARNING: The NVIDIA Driver was not detected.  GPU functionality will not be available.
   Use 'nvidia-docker run' to start this container; see
   https://github.com/NVIDIA/nvidia-docker/wiki/nvidia-docker .

NOTE: MOFED driver for multi-node communication was not detected.
      Multi-node communication performance may be reduced.

root@4f28a8275d2d:/workspace#
```

#3.関連リンク

* [Cannot use GPU support in Windows 10 preview build 21327](https://github.com/microsoft/WSL/issues/6617)
* [Announcing Windows 10 Insider Preview Build 21332](https://blogs.windows.com/windows-insider/2021/03/10/announcing-windows-10-insider-preview-build-21332/)
ColabratoryでJavaScriptを実行して表示する

Google Colabratory は Python スクリプトを実行するノートブックですが、JavaScript を実行して出力することができます。

このノートブックが元ネタです。
JavaScript のスニペットがノートブックでためせます。
>[advanced_outputs.ipynb](https://colab.research.google.com/notebooks/snippets/advanced_outputs.ipynb#scrollTo=dBnNMBxm2L6I)

###JavaScript (DOM) を実行して表示
IPython.display.Javascript() で実行・表示します。

```Python
import IPython
js_code = '''
document.querySelector("#output-area").appendChild(document.createTextNode("hello world!"));
'''
display(IPython.display.Javascript(js_code))
```

>hello world!

JavaScriptはノートブックのドキュメントに保持され、別のセルで実行しても保持されています。

```Python
display(IPython.display.Javascript(js_code)) # 別セルで実行しても出力される
```
>hello world!


🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
Tensorflow Object Detection API でのデータ拡張（data augmentation）

pipeline.config ファイルの train_config に data_augmentation_options を記述します。
関数名と引数を指定すると、main.py実行でデータ拡張オプションを適用してくれます。

```pipeline.config
train_config {
  batch_size: 1
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
  data_augmentation_options {
    random_crop_image {
      min_object_covered: 0.0
      min_aspect_ratio: 0.75
      max_aspect_ratio: 3.0
      min_area: 0.75
      max_area: 1.0
      overlap_thresh: 0.0
    }
  }

```

可能なオプションは以下。

https://github.com/tensorflow/models/blob/2986bcafb9eaa8fed4d78f17a04c4c5afc8f6691/official/vision/beta/ops/preprocess_ops.py

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
OpenCVのcv2.VideoCaptureで任意の秒数から読み込み

単純に秒数ではセットできないので、fpsを取得してかけます。

```python

cap = cv2.VideoCapture(video_path)
read_fps= cap.get(cv2.CAP_PROP_FPS) # 1秒あたりのフレーム数を取得
start_point = 20 # 20秒後から読み込む
cap.set(cv2.CAP_PROP_POS_FRAMES, start_point * read_fps) # 秒数と１秒あたりフレーム数をかけたフレームからスタート
```

10時間を超えるような動画だと、保持しきれなくてズレるので注意。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[PHPUnit]10分でできる！はじめてのPHPUnit

はじめてPHPのテスティングフレームワークであるPHPUnit使ったので、覚え書き。
本手順では、Composerではなく、Pharを使います。
インストールから、サンプルコードを使ったテスト実行まで、10分あればできちゃいます♪

## 環境
* OS: Amazon Linux2
* PHP: PHP 7.4.15
* PHPUnit: 9.5.2

※PHPUnit9.5を使うには、PHPのバージョンが7.3以上である必要があります。

## インストール

(1) まず、以下のコマンドを実行し、phpunit-9.5.pharをダウンロード。

```
$ wget https://phar.phpunit.de/phpunit-9.5.phar
```

(2) 実行権限を付与します。

 ```
$ chmod +x phpunit-9.5.phar
 ```

(3) バージョン確認

```
$ php phpunit-9.5.phar --version
PHPUnit 9.5.2 by Sebastian Bergmann and contributors.
```

(4) ファイル名をリネームします

```
$ mv phpunit-9.5.phar phpunit
```

(5) Pathを確認し、優先順位が最も高いPathを確認します。

```bash
$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/ec2-user/.local/bin:/home/ec2-user/bin
```

一番左に表示されているPathが最も優先順位が高いです。
上記の場合は、/usr/local/binですね。

(6) (5)で確認したPathに、phpunitファイルを移動させます。

```
$ mv phpunit /usr/local/bin/
```

(7) 以下のコマンドを実行して、phpunitのバージョンが出力されればOK。

```
$ phpunit --version
PHPUnit 9.5.2 by Sebastian Bergmann and contributors.
```

## サンプルコードでLet'sテスト

(1) 任意のディレクトリで、テストコードstackTest.phpを作成します。

```php:stackTest.php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class StackTest extends TestCase
{
    public function testPushAndPop(): void
    {
        $stack = [];
        $this->assertSame(0, count($stack));

        array_push($stack, 'foo');
        $this->assertSame('foo', $stack[count($stack)-1]);
        $this->assertSame(1, count($stack));

        $this->assertSame('foo', array_pop($stack));
        $this->assertSame(0, count($stack));
    }
}
```

このコードは、公式ドキュメントの
[2. Writing Tests for PHPUnit | PHPUnit 9.5 Manual](https://phpunit.readthedocs.io/en/9.5/writing-tests-for-phpunit.html)
より、拝借しました。

(2) テスト実行してみます。

```
$ phpunit stackTest.php
PHPUnit 9.5.2 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:00, Memory: 18.00 MB

OK (1 test, 5 assertions)
```

うまくいきました！

## 参考
* [Getting Started with PHPUnit 9 | PHPUnit](https://phpunit.de/getting-started/phpunit-9.html)
* [1. Installing PHPUnit | PHPUnit 9.5 Manual](https://phpunit.readthedocs.io/en/9.5/installation.html)
* [2. Writing Tests for PHPUnit | PHPUnit 9.5 Manual](https://phpunit.readthedocs.io/en/9.5/writing-tests-for-phpunit.html)
* [Pathを通すとは、環境変数とは | Qiita](https://qiita.com/fuwamaki/items/3d8af42cf7abee760a81)
* [PHPUnitのインストールが簡単になってる！！ | Qiita](https://qiita.com/goosys/items/68c491c5996174de0b4f)
オムニチャネルスーパーバイザタブが表示されない

なかなか、気付かない。分かれば簡単な解決方法。

回避方法
SalesforceClassicでプロファイルのオムニチャネルを有効にすることでした。どうやら、Classicで非表示になっていると、Lightningでも非表示になります。

https://trailblazers.salesforce.com/answers?id=9064S000000Dh7Y
Ruby クラス

初心者の個人的なメモですがよければどうぞ。


## クラスの定義
クラス名は大文字で始める。JSと一緒。

```ruby
   class Person
   
   end
```

## attr_accessor
クラスのデータを定義する方法の一つ。Menuクラスのインスタンスにnameという情報を持たせることができます。
このnameという情報のことをインスタンス変数と呼びます。インスタンス変数は複数持つことができる。

```ruby
   class Person
　　　attr_accessor :name   
　　　attr_accessor :age  
   end
```
## インスタンスの作成
クラスに.(ドット)をつけてnewとする。

```ruby
   Person.new
```
## インスタンス変数に代入

```ruby
   Person.name = "げん"
```

## クラス内でメソッドを定義
シンプルにクラス内でdefを使うだけ。

```ruby
   class Person
　　　attr_accessor :name   
　　　attr_accessor :age  

     def talk
       puts "こんにちは"
     end       
   end

   gen = Pesron.new
   gen.talk  #呼び出し
```

## self
self.変数名 とすることでクラス内の変数を使用することができる。selfにはインスタンス自信が含まれる。

```ruby
   class Person
　　　attr_accessor :name   
　　　attr_accessor :age  

     def talk
       return "私は#{self.age}歳です"
     end       
   end

   gen = Person.new
   gen.age = 2
　　puts gen.talk  #私は2歳です が出力される。

```

## initializeメソッド
クラスからnewでインスタンスを生成した直後に自動で呼び出される。

```ruby
   class Person
　　　attr_accessor :name   
　　　attr_accessor :age  
     
     def initialize(name:,age:)
        self.name = name
        self.age = age
     end    
  
     def talk
       return "#{self.name}です。#{self.age}歳です"
     end       
   end

   person1 = Person.new(name:"げん",age:2) #この時点でinitializeメソッドが実行され、インスタンス変数に引数の値が代入される
   

```
## ファイル分割
別ファイルで管理しているコードを読み込むにはrequireを使用する。
JSでバックエンド書いたときもrequireを使った。

```ruby
   require './index2'
```
## gets.chomp
コンソールが入力待ちの状態になる。
入力された値は数字だとしても文字列に変換される。

## gets.chomp.to_i
コンソールでの入力され、文字列として扱われる数字を、数値に変換。
to inteager ということかな??

```ruby
  nun = gets.chomp.to_i
```

## 継承
新しいクラス名　< もとのクラス名　の形で書く。
新しいクラスは子クラス、元のクラスは親クラスという。

```ruby
   class Teacher < Person
   end
```

## オーバーライド
親クラスで定義されたメソッドを、同じ名前で子クラスで上書きすること。
initializeメソッドもオーバーライドできる。

##　super
子クラスの親クラスのメソッドをオーバーライドするとき、重複する部分があればsuperとすることで同名のメソッドを呼び出すことができる。親クラスと子クラスで同じコードを書く必要がなくなる。

```ruby
     class Person
　　　attr_accessor :name   
　　　attr_accessor :age  
     
     def initialize(name:,age:)
        self.name = name
        self.age = age
     end    
  
     def talk
       return "#{self.name}です。#{self.age}歳です"
     end       
   end
   

    class Teacher < Person
　　　attr_accessor :subject   
     
     def initialize(name:,age:,subject:)
        super(name:name,age:age)
        self.subject = subject
     end    
  
     def talk
       return "#{self.name}です。#{self.age}歳です"
     end       
   end

```

## Dateクラス
rubyで日付を扱うときに使用するクラス。

```ruby
require "date"

date1 = Date.new(2021.3.10)
```
### 曜日判定
日曜日かどうか判定するには、作成されたインスタンスの後にsundayを書き、?をつける。

```ruby
   date1.sunday?  #真偽値が返る
```

### 今日の日付
```ruby
   today = Date.today   #newがいらない
```
Date.todayのようにクラス名に対して呼び出したメソッドをクラスメソッドという。

## クラスメソッド
この書き方でクラスメソッドが定義できる。

```ruby
   def クラス名.メソッド名
   end
```
【Power Automate】SharePointリスト取得時のnull判定

# Sharepointリスト取得時のnull判定
HTTPプレミアコネクタを使ってスクレイピングした結果をSharePointリストに差分登録する際、リストのnull判定(初回実行時はnull)が分かりにくかったので投稿します。

## はまったポイント
SharePointリストに対して「複数の項目の取得」で配列を取得した後、スクレイピング結果と突合したくて変数に「タイトル」を入れるステップを定義したら「Apply to each」のステップが自動で追加された。リストの取得結果がnullだと「Apply to each」は一度も実行されない。

## null判定
以下の感じで先にnull判定が必要。式は「empty(outputs('複数の項目の取得')?['body/value'])」が「次の値に等しくない」が「true」みたいな書き方。

![automateの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681426/1f7c9d6e-e76f-2b6d-d904-e24e28ae0267.png)
Ruby メソッド

初心者の個人的なメモですけどよければどうぞ。

## メソッドの書き方

Rubyでは関数のことをメソッドという？

```ruby
def メソッド名
   処理
end
```

## メソッド呼び出し
```ruby
def introduce 
  puts "はじめまして"
　puts "こんにちは"　
end

introduce   #呼び出し
```

## メソッド　引数あり
引数ありのメソッドは実行するためにはメソッド名(引数)の形で行う。
引数ありのメソッドを()なしで実行しようとするとエラーが起こる。

```ruby
def introduce(name) 
  puts "はじめまして"
　puts "#{name}です"　
end

introduce("げん")   #呼び出し
```
## メソッドの戻り値
JS同様にreturnを記載。

```ruby
def メソッド名
   処理
　　return 戻り値
end
```

## 真偽値を返すメソッド
真偽値を返すメソッドはメソッド名の後に?をつける慣習がある。

```ruby
   def judge?(price)
       return price > 1000
   end
```
```ruby
   judge?(2000) #trueが返る
```
これを用いて条件分岐もできる

```ruby
   if judge?(2000)
      puts "高いです"
　　else
     puts "安いです"
   end 
```
## returnはメソッドを終了させる役割もある
JSでもこの機能はある。

## キーワード引数
メソッドの引数の後に「:」をつけると、そのメソッドの実行のために引数を指定する時に、何がどの引数かがわかりやすく記述することができる。

```ruby
   def introduce(name:,age:,country:)
       puts "僕の名前は#{name}です、"
       puts "年齢は#{age}です。"
       puts "#{country}出身です"
   end
```

呼び出し

```ruby
   introduce(name:"げん",age:"2",country:"日本") 
```