OmniAICreator/Qiita-1.07M huggingface dataset:
Railsアプリに環境変数の変更を反映できなかった話

## TL;DR

Railsアプリで使用しているJavascriptで読み込んでいるAPIキーを変更したのに切り替わらなくて半日を無駄にした話(解決済)

## 状況

Ruby on Rails 5アプリ内で使用しているJavascriptへerbとして環境変数からAPIキーを読み込むようにしていた。
イメージとしては以下のような感じ。

```.env
# .envなど、環境変数を設定できるようなファイル内
API_KEY=sampleApiKey
```

```call_api.js.erb
function() {
    // 略
    api_key=<%= ENV['API_KEY'] %>
    // 略
}
```

検証環境に開発環境のAPIキーを環境変数で入れてしまっていたため環境変数を修正した。

が、Passengerを再起動しようがNginxを再起動しようが`source`コマンドを打とうが、
なんならサーバごと再起動しようが **変更前のAPIキーで動いてしまっていた。**

ちなみに検証環境では本番同等の環境ということで `RAILS_ENV=production` で動かしている。
勘の良い皆様ならもうお気づきでしょう、**precompileの存在に......**

## 結論

設定にもよりますが、一般的にproductionモードでRailsアプリを起動する前にはprecompileを行います。
precompileが何って人は公式を確認いただければと思います。
参照：[アセットパイプライン - Railsガイド](https://railsguides.jp/asset_pipeline.html)

今回も検証環境へデプロイを行った際にprecompileが走っていたのですが、
その時点での環境変数=変更前の環境変数をjsへ取り込んでしまっていたようです。
そりゃ環境変数書き換えても意味ないですよね。

precompileがjsをminify & uglifyしてくれるのは知っていましたが、
環境変数を埋め込むタイミングを見誤っていました。

## 解決策

precompileし直せばいいだけの話なので、手動で行う際は[railsのProductionで手動でPrecompileし直す](https://qiita.com/gymnstcs/items/00ae23b7fdf0c69b57c5)を参考に実施すれば良いです。
今回は再デプロイを行うことで解消しました。

## 終わりに

普段はCI/CDツールでGitHubの特定ブランチへマージした段階で自動デプロイが走り、
その際にprecompileを行う設定にしていたので完全に頭から抜けていました。
焦るとなかなか当たり前のことでも気づけないものですね。
NotionでデータベースをCSVでエクスポートする

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2020](https://qiita.com/advent-calendar/2020/notion) 10日目のエントリです。
9日目は[Notionでページのコメントを非表示にする](https://qiita.com/pictiny/items/87d8ec343deddff54dff)でした。

# データベース
Notionでは[データベース](https://qiita.com/pictiny/items/dba21dd5d226ac5b6849)を作ることができます。
データベースの情報をCSVで吐き出したいことがあります。

## CSVエクスポート
右上のメニューから `Export` を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/d6113a1e-f507-810b-741c-2dcc0dc36705.png)

`Markdown & CSV` を選択して `Export` をすると、CSVファイルの入ったzipファイルがダウンロードできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/aba17610-7060-26a1-7fd9-f57fdc37a452.png)

## サブページ
CSVファイルには、ページタイトルと[プロパティ](https://qiita.com/pictiny/items/dba21dd5d226ac5b6849#%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3)の情報しか含まれていません。

エクスポートのモーダルで `Include subpages` のオプションを選択すると、zipファイルにページコンテンツのMarkdownファイルが含まれるようになります。

# まとめ
公式ドキュメントは[Export a database as CSV](https://www.notion.so/Export-a-database-as-CSV-89654fbb61264d5eb2025a7606a8e3d4)にありますので、そちらもご覧ください。
M1 MacでReact NativeのFlipperのビルドがこける時

2020/12/11追記: 実機（iPhone 11）で試してみたら動かなかったので、記述を追加

---

[IwaiさんのM1 MacでのReact Native開発環境を整える](https://zenn.dev/myb/articles/4b1dd3821703aa2ac95b)を読んで、だいたいビルドできるようになったのですが、Flipperのビルドがこけるのが気になっていました。

```
libFlipperKit.a, building for iOS Simulator-x86_64 but attempting to link with file built for iOS Simulator-arm64
```

こういう感じのエラーが出ます。ググってもさっぱりだったので、神頼みでPodfileに下記の記述を追加したところ通るようになりました。（`###`で始まるコメントの記述内容を追記）

```ruby
  post_install do |installer|
    flipper_post_install(installer)

    installer.pods_project.build_configurations.each do |build_configuration|
      build_configuration.build_settings['ONLY_ACTIVE_ARCH'] = 'No'
      ### 次の行に`i386`を追加
      build_configuration.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64 i386"
      ### 次の行を追加
      build_configuration.build_settings["EXCLUDED_ARCHS"] = "armv7"
    end

    installer.aggregate_targets.each do |aggregate_target|
      aggregate_target.xcconfigs.each do |config_name, config_file|
        ### 次の行に`i386`を追加
        config_file.attributes['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] ='arm64 i386'
        ### 次の行を追加
        config_file.attributes['EXCLUDED_ARCHS'] ='armv7'
        config_file.save_as(aggregate_target.xcconfig_path(config_name))
      end
    end
  end
```

いずれ多分ちゃんとした対応方法が出てくると思うのですが、応急処置としては使えると思うので書いておきます。
[基礎] webアプリケーションのサーバーサイドの構成


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/912965/9adf72d5-6706-f131-f40a-3ec9693aab9b.png)


１, webサーバー
---
リクエストを処理して、レスポンスを返却する役割

２, アプリケーションサーバー
---
webサーバーからリクエストを受け取って処理をし、
HTMLなどをwebサーバーへ返却する役割


３, データベースサーバー
---
アプリケーションで使用するデータを管理する役割
認定 Platform デベロッパー資格の更新 (Winter '21)　⇒　項目レベルとオブジェクトレベルのセキュリティや安全なナビゲーション演算子を使ってみる

ハンズオンの Challenge
>Enforce Field and Object Level Security and Use the Safe Navigation Operator in Apex
Simplify your code by using the Security.stripInaccessible method in the Apex class. Also catch any null references using the Safe Navigation operator.

>Note: Complete the necessary setup configuration in the Unit text prior to the hands-on challenge section.
Create a new Apex class
Name: ApexSecurityRest
Copy and paste the ApexSecurityRest code provided above.
Use the Security.stripInaccessible method logic to process the results. Remove fields that the user does not have Read access to.
Remove the redundant object- and field-level access checks for Name and Top_Secret. Note: Delete the unneeded code rather than commenting it out.
Apply the Safe Navigation operator functionality to Account in order to avoid null references.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/b2172d11-5541-183c-3a18-c16eca07b406.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/e43ca53a-5786-2473-a970-3aa7b7b04310.png)

```ruby:ApexSecurityRest.apxc
@RestResource(urlMapping='/apexSecurityRest')
global with sharing class ApexSecurityRest {
    @HttpGet
    global static Contact doGet() {
        Id recordId = RestContext.request.params.get('id');
        Contact result;
        if (recordId == null) {
           throw new FunctionalException('Id parameter is required');
        }

        List<Contact> results = [SELECT id, Name, Title, Top_Secret__c, Account.Name FROM Contact WHERE Id = :recordId];
        SObjectAccessDecision securityDecision = Security.stripInaccessible(AccessType.READABLE, results);
        
        if (!results.isEmpty()) {
            result = results[0];
            if (Schema.sObjectType.Contact.fields.Description.isUpdateable()){
                result.Description = result.Account?.Name;
            }
        }
        
        return result;
      }
      public class FunctionalException extends Exception{}
      public class SecurityException extends Exception{}
}
```
【FileMaker】10分たったらまたログインしてね

タイトルのまんまなんですが、FileMakerでセキュリティ設定をしてログインする場合、ある一定の時間が経つとまたログインを求められます。

これは、fmreauthenticate10という元々設定されている拡張アクセス権のキーワードが関係しています。
![スクリーンショット 2020-12-10 22.02.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/81e6c62b-4111-3b1e-0178-a2783f7a0670.png)
FileMaker Proでも、FileMaker Goでも同様です。
特に、FileMaker Goでは、アプリを切り替えて色々と操作することが多いと思います。
バックグラウンドに行った時にいきなりファイルが終わってしまうということはなくずーっと起きて色々やってくれています。（いわゆるマルチタスク）

システムにログインして何も操作していない時、デフォルトで10分間は再ログインしなくてもファイルを操作できます。
10分過ぎたらまたログインを求められます。

なぜ10分なのか？

fmreauthenticate10の"10"が10分のことを指しているからです！

えーって思いますが、そうなんですって、奥さん。

つまり、"10"を違う数字にすれば、その数字分認証が続いていることになります。
"8"にすれば8分、"100"にすれば100分です。
最長10080分！！(168時間=7日!!)
変更は、拡張アクセス権の編集で、末尾の数字を変えるか、新たに末尾を変更したfmreauthenticateを作成して該当のアクセス権セットで拡張アクセス権にチェックを入れるだけです。
![スクリーンショット 2020-12-10 22.41.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/78ed11b0-a7d9-134e-9585-35755b009610.png)

用途によっては長い時間でいいのですが、特にFileMaker Goはモバイル端末で稼働することから、使用しているFileMakerアプリが人目にさらされることが多い場合は、短い時間に設定して、不用意にアプリを覗かれないように（ログインできないように）対策をしておくことも大事です。

こちらのFileMaker 19 ヘルプのページが本家ですので、紹介しておきます。
[拡張アクセス権の作成と編集](https://help.claris.com/ja/pro-help/content/managing-extended-privileges.html)
Google Apps Scriptで過去のある月から今月までの月初日をループで取得する

## はじめに
Google Apps Scriptで過去のある月から今月までの評価データを取得するタスクを依頼されました。その際、過去のある月から今月までの月初日をループで取得する処理を書いたのですが、少し工夫が必要だったのでメモとして残しておこうと思います。

# 処理と解説
##### 処理
```javascript
function myFunction() {                                                                  // 1行目
  const currentDate = new Date();                                                        // 2行目
  currentDate.setDate(1);                                                                // 3行目
  currentDate.setHours(0, 0, 0, 0);                                                      // 4行目
  const yearDates = [];                                                                  // 5行目
  for (let d = new Date('2020/01/01'); d <= currentDate; d.setMonth(d.getMonth() + 1)) { // 6行目
    const loopDate = new Date(d);                                                        // 7行目
    yearDates.push(loopDate);                                                            // 8行目
  }                                                                                      // 9行目
  Logger.log(yearDates);                                                                 // 10行目
}
```
##### 結果
```javascript
[
    Wed Jan 01 00:00:00 GMT+09:00 2020,
    Sat Feb 01 00:00:00 GMT+09:00 2020,
    Sun Mar 01 00:00:00 GMT+09:00 2020,
    Wed Apr 01 00:00:00 GMT+09:00 2020,
    Fri May 01 00:00:00 GMT+09:00 2020,
    Mon Jun 01 00:00:00 GMT+09:00 2020,
    Wed Jul 01 00:00:00 GMT+09:00 2020,
    Sat Aug 01 00:00:00 GMT+09:00 2020,
    Tue Sep 01 00:00:00 GMT+09:00 2020,
    Thu Oct 01 00:00:00 GMT+09:00 2020,
    Sun Nov 01 00:00:00 GMT+09:00 2020,
    Tue Dec 01 00:00:00 GMT+09:00 2020
]
```

処理を大まかに説明すると下記のようになります。
・2行目で現在の日付を取得。
・3～4行目で日付と時間を1日の0時に設定。
・5行目で今年の月初日を格納する配列yearDatesを初期化。
・6行目からのfor文で2020/01/01から今月までループし、8行目でyearDatesに今年の月初日を格納。

for文の中の7行目で新しく日付オブジェクトを生成しているのは、初期化式の変数dをyearDatesに追加すると、yearDatesに追加される値が全て、dのループの最終更新の値となるためです。
8行目を `yearDates.push(d)` に書き換えると下記のような結果となります。

```javascript
[
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021,
    Fri Jan 01 00:00:00 GMT+09:00 2021
]
```
yearDatesに追加される値が全て、dの日付オブジェクトになるため、このような結果となります。
これを回避するため、7行目でループの度に毎月異なる日付オブジェクトを生成して追加しています。
AWSにデプロイしたLaravelのログを見やすくした

## はじめに
ECSにLaravelをデプロイしているときにCloudWatchLogsにログを吐いていたが
不具合が起こったときに調査しやすくするためにlogをjson化してなおかつ
同一リクエストのログをまとめて取得したかった

## 前提
ECSにデプロイしているALBを使用している時

## コード

ALBを経由したリクエストには`X-Amzn-Trace-Id`というヘッダーに
リクエストごとに固有のIDが振られるのでログに吐いておくと
あとで確認しやすい

```php:app/Log/JsonFormatter.php
<?php

declare(strict_types=1);

namespace App\Log;

use Illuminate\Http\Request;
use Monolog\Formatter\NormalizerFormatter;

class JsonFormatter extends NormalizerFormatter
{
    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        $request = resolve(Request::class);
        $output = [];
        $output['level'] = $record['level_name'];
        $output['xAmznTraceId'] = $request->header('X-Amzn-Trace-Id');
        $output['message'] = $record['message'];
        foreach ($record['context'] as $var => $val) {
            $output[$var] = $val;
        }

        return json_encode($output, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
    }
}
```
phpコンテナの出力はstderrに出てくるので
logging.phpを以下のように修正

```php:config/logging.php
       'stderr' => [
            'driver'    => 'monolog',
            'handler'   => StreamHandler::class,
            'formatter' => \App\Log\JsonFormatter::class,
            'with'      => [
                'stream' => 'php://stderr',
            ],
        ],
```
QMLアプリのデータ保存

## Qtアプリにおけるファイル保存

通常のQtアプリ(C++)でアプリ設定を保存することを考えるとき、通常ユーザーフォルダなどにiniファイルで保存します。QtではQSettingsクラスを使うのが一般的です。

- Qtアプリの設定を保存する方法(QSettings)
  - https://qiita.com/kanryu/items/b5b3064b6ce4fd94dac8


## QMLアプリにおけるファイル保存

`Qt.labs.settings` を使用します。

https://doc.qt.io/qt-5/qml-qt-labs-settings-settings.html

QMLアプリの場合、Android/iOS等の他のOSへのサポートを考慮されているためか、ファイル名を指定して保存、ロードするという仕組みにはされていないようです。

## 動作例

例として、Windowに保存ボタンを配置しただけの簡単なアプリを考えてみましょう。

```qml
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.0
import Qt.labs.settings 1.0

ApplicationWindow {

    id: _root
    width: 640
    height: 480

    Button {
       text: "設定を保存する"
       onclick: settings.sync()
    }

    Settings {
        id: settings
        property alias x: _root.x
        property alias y: _root.y
        property alias width: _root.width
        property alias height: _root.height
    }
}
```

`Settings { }` と書いた範囲が保存対象となります。idを `settings` とした場合に、 `settings.sync()` を呼び出すと現在の値がファイルとして保存されます。この辺はQSettingsと同じですね。

QSettingと違うところはセクションがなかったりファイル保存形式の指定がないところで、スマフォ向けのOSだとファイルIOが隠蔽されているためアプリ開発者からすると詳細を知る方法もあまりなく、ちゃんと保存できているならばフレームワーク任せでも良いと思います。

Settingsタグに書く `property` は、サンプルのように `property alias` で他のUI要素のパラメータにリダイレクトしてもいいですし、単に `property var` として 保存できる変数扱いにしてもいいでしょう。

Settingsに関してはAPIがシンプルなのでこれ以上特に語ることはなさそうですね。

なにか疑問や質問がある方はコメントをください。
TSとReact(17系)でeslintがVSCodeでファイル保存時にフォーマットされるやつを作る

久しぶりにCRAをTSつきで使ったら、ちょいちょい詰まったのでメモ :penguin: 

### プロジェクトの作成

```sh
# プロジェクト作成
npx create-react-app app --template typescript
# React17系から`React`のimport文は必要ないので削除
npx react-codemod update-react-imports
```

### 問題
VSCodeで `Cannot use JSX unless the '--jsx' flag is provided.` と出る

**解決策**
エディタの右下の`4.0.3`の部分をクリックし、TSのバージョン選択で、`package.json`で指定しているTSのバージョンと合わせる
![Screen Shot 2020-12-10 at 21.23.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117615/4ec9fa90-b6d4-eec1-a306-2cfe4f00871e.png)


#### 参考
https://stackoverflow.com/questions/64974648/problem-with-visual-studio-code-using-react-jsx-as-jsx-value-with-create-react

### ESLintの設定

```sh
# eslint初期化
$ npx eslint --init
# 以下、対話形式の質問と回答
✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · Yes
✔ Where does your code run? · browser
✔ How would you like to define a style for your project? · guide
✔ Which style guide do you want to follow? · airbnb
✔ What format do you want your config file to be in? · JSON
✔ Would you like to install them now with npm? · Yes
```

上記で生成された `.eslintrc.json`に以下を追加

```json
  {
    "settings": {
        "import/resolver": {
        "node": {
            "extensions": [".js", ".jsx", ".ts", ".tsx"]
        }
        }
    },
    "rules": {
        "@typescript-eslint/indent": [
            "error",
            2
        ],
        "@typescript-eslint/prefer-interface": "off",
        "react/jsx-filename-extension": [
            "error",
            { "extensions": [".jsx", ".tsx"] }
        ],
        "react/prop-types": "off",
        "spaced-comment": [
            "error",
            "always",
            { "markers": ["/ <reference"] }
        ],
        "react/react-in-jsx-scope": 0,
        "import/extensions": 0
    }
  }

```

#### 参考
https://ginpen.com/2019/08/06/eslint-for-react-in-typescript/

### VSCodeに必要な設定
保存時にeslintのフォーマットが行われる

```json
{
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    }
}
```
Dartのmixinを学んで見る

最近お気に入りのresocoderさんの、[mixinに関する記事](
https://resocoder.com/2019/07/21/mixins-in-dart-understand-dart-flutter-fundamentals-tutorial/)で学習しました。

# Mixinが必要になるストーリー

## 単一継承でうまくいっているパターン
- `Mosquito`クラスが抽象クラス`AirborneInsect`を継承(`extends`)します。
- `AirborneInsect`クラスは`flutter()`、`buzz()`というメソッドを持っています。
- `Mosquito`クラスのインスタンスは `flutter()`呼び出せます！

## 単一継承でうまくいかないパターン
- 昆虫だけでなく、鳥も扱うことになりました！
- 抽象クラス`Bird`で`flutter()`を持ちます。
- `Bird`を継承した`Swallow`で`flutter()`を呼び出せます！
- しかしこの`flutter()`は`AirborneInsect`と`Bird`で重複しています！

## 複数の抽象クラスが同じメソッドを持つ重複を解決: mixin
ここで多重継承を可能にする`mixin`を使います。
以下のコードでは`Fluttering`クラスを、`AirborneInsect`と`Bird`適用しています。

これでコードの重複がなくなりました！

### 実際のコード

```dart
mixin Fluttering {
  void flutter() {
    print('fluttering');
  }
}

abstract class Insect {
  void crawl() {
    print('crawling');
  }
}

abstract class AirborneInsect extends Insect with Fluttering {
  void buzz() {
    print('buzzing annoyingly');
  }
}

class Mosquito extends AirborneInsect {
  void doMosquitoThing() {
    crawl();
    flutter();
    buzz();
    print('sucking blood');
  }
}

abstract class Bird with Fluttering {
  void chirp() {
    print('chirp chirp');
  }
}

class Swallow extends Bird {
  void doSwallowThing() {
    chirp();
    flutter();
    print('eating a mosquito');
  }
}
```

# Mixinの使い方
`mixin`で定義して、`with`句で適用します。
fieldとmethodを継承できます。また、複数mixinを適用できます。
また`mixin`は親クラスに適用され、新しい匿名クラスを生成しているようです。

```dart
// mixinの定義
mixin M1{
  int number = 42;
  void say() => print('M1!');
}
mixin M2{
  String name = 'M2';
  void hello() => print('hello!');
}

// mixinの適用
class C extends Object with M1, M2 {}

main() { 
  var c = C();
  c.say();          // M1!
  c.hello();        // hello!
  print(c.number);  // 42
  print(c.name);    // M2
}
```

まずはコードの重複をなくす目的で使ってみると良いと思います。
<自分メモ>MySQLでテーブルの削除、新規作成後、ターミナルでテーブルのデータが表示できず実行エラーになってしまう(mac,PHP,Docker)

#環境
Docker Composeでappコンテナとdbコンテナを立ち上げる
↓docker-compose.yml
appコンテナ　php:7.4-apache
dbコンテナ　mysql:5.5

既存のMySQLテーブルを削除、新規作成し、ターミナルで動作確認する。
#行ったこと
1.テーブルを```DROP TABLE IF EXISTS テーブル名```で削除し、新しいテーブルの作成をする。

2.テーブルが出来ているか、MySQLで確認。```SHOW  TABLES;```無事確認。
```SELECT * FROM memo;```でテーブルを確認。

```
MySQL [book_log]> SELECT * FROM memo;
+----+------+
| id | memo |
+----+------+
|  1 |      |
+----+------+
```
謎の空白ができてしまい。調子が悪いのかなと再度登録。
無事登録できたのですが、ターミナルでの実行結果がエラー。

``````
MySQL [book_log]> SELECT * FROM memo;
+----+-----------+
| id | memo      |
+----+-----------+
|  1 |           |
|  2 | テスト      |
|  3 | テスト      |
+----+-----------+

```
↓ターミナル

```
[メモ一覧表示]
[10-Dec-2020 20:46:31 Asia/Tokyo] PHP Warning:  mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, bool given in /var/www/html/tmp/memo.php on line 35

Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, bool given in /var/www/html/tmp/memo.php on line 35
[10-Dec-2020 20:46:31 Asia/Tokyo] PHP Warning:  mysqli_free_result() expects parameter 1 to be mysqli_result, bool given in /var/www/html/tmp/memo.php on line 40

Warning: mysqli_free_result() expects parameter 1 to be mysqli_result, bool given in /var/www/html/tmp/memo.php on line 40
```

翻訳

```
1行目
mysqli_fetch_assoc() は、パラメータ 1 が mysqli_result であることを期待していますが、これは /var/www/html/tmp/memo.php の 35 行目で指定された bool です。
2行目
mysqli_fetch_assoc（）は、パラメーター1がmysqli_resultであると想定しています。
3行目
警告: mysqli_free_result() は、40 行目の /var/www/html/tmp/memo.php でパラメータ 1 を mysqli_result, bool とします。
4行目
警告: mysqli_free_result() は、40 行目の /var/www/html/tmp/memo.php でパラメータ 1 を mysqli_result, bool とします。
```
この結果から先ず、どんな値を取得しているのか、var_dumpで確認すると
falseになっていました

上手くデータを取得できていないという事なのかな思い、[以前](https://qiita.com/sakuma-s-Qiita/items/9f41babc0bfc698fc43e)　書いた記事と同じ現象だったので実行することに。
<strong>MySQLを終了し、dockerをストップ、dockerを再度起動させ、MySQLを起動。</strong>
この流れで再度、ターミナルで実行してみると成功！！

```
番号を選択してください:2

[メモ一覧表示]
1

----------------
2
テスト
----------------
3
テスト
----------------
4
テスト2
----------------
5
テストする
----------------
```

無事表示されました！！！
Dockerの仕組みの理解がかなり不足している痛感いたしました。

何かご指摘やお気づきのことがあれば初学者の自分にとって凄くありがたいことなので是非、お願いいたします！！！！！
VCIで出来ないこと　その３　スクリプト編


この記事はVCIアドベントカレンダー2020の参加記事です

# 内容を三行で
1. できる範囲でやりたいことを実現しよう！
2. 今回はunityでの設定でできないことをご紹介します。
3. 3つに分けたので今後の記事も参考にしてね

# 敵を知り己を知れば百戦殆うからず
ネガティブなことを言うなと言われるかもしれませんが、何ができないか予め把握した上で、やりたいことを実現する方法を考えましょう。じゃないと、時間をかなり無駄にしてしまうこともあるので目を背けてはいけないと思います（百敗くらい）。ここではスクリプトでできないことを紹介します。前回記事[unity上の設定でできないこと](https://qiita.com/sakkinonana/items/f450b0506bde991a7c96)や、[VCIの仕様](https://qiita.com/sakkinonana/items/088b015456a238e50e54)については別の記事で触れたいと思います。

## スクリプト
1. 部屋（スタジオ・ルーム）をまたいだ情報の保存
2. 外部通信
3. ファイルの保存
4. 直接的な速度の設定・取得
5. physical update
6. luarockなどでインストールするような外部ライブラリインポート

### 部屋（スタジオ・ルーム）をまたいだ情報の保存
場所を移動したときにはそれまでの処理内容やアイテムそのものなどを受け継ぐことは出来ません。
唯一VCIの位置だけは保存されます。アップデートや落ちたときにはリセットされてしまうので完全な代替にはならないですが、どうしても何か保存したいときは使ってみてください。

### 外部通信
ネットワーク上から情報を拾ってきたり、逆にリクエストを送って保存しておくようなことも出来ません。
これが出来たら色々できそうなのですが、残念ながら対応してません。ただ、進捗報告会で開放されていないもののできるようには作っているそうなので、開発が進むのを待ちましょう。

### ファイルの保存
ファイルの保存などに関係する関数は存在しますが、実行時に無視されてしまいます。
一応手元では調べ尽くしたと思いますが、あんまり公開するのもはばかられるので公開はしません。興味があったらご自身の目で確かめてみてください。

### 直接的な速度の設定・取得
直接的に速度をいじるような関数はありません（angular velocityを除く）。同様に取得もできません。速度を付加する際はaddforceを、速度を取得する際はpositionとtimeとから取るしかなさそうです。ただしこれはかなりブレるので（[コチラ](https://qiita.com/sakkinonana/items/21bc25461577cef1357c)を参照）工夫が必要です。

### physical update
unityにはfpsを無視して一定間隔で実行するupdate関数もあるようです。これにアクセスできれば上記の問題は解決なのですが、現状アクセスできないようです。

### luarockなどでインストールするような外部ライブラリインポート
だいぶ残念だったのですが、luaならtorch使えるのでは！？とか思ったりする方もいらっしゃるかと思うのですが、残念ながらインポートできるのは標準のものと、自作のものだけです。
PHP  var_dump


<p>
PHPで配列の中身を知りたいときに使う。

<p>
<p>

```
var_dump($知りたい配列の変数)
```

<p>
例えば
＄nameの中身に何が入ってるか知りたい

var_dump($name)

で中身が知れます。

便利です。
人工知能とチャットボットについて知っておくべきことすべて

![possessed-photography-zbLW0FG8XU8-unsplash (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605616/c6b8c093-04e4-12db-e264-ba82e287d76a.jpeg)
この記事では、出会い系サービスで人工知能を使用する秘訣と、出会い系サイトのチャットボットがユーザーとどのように会話するかを明らかにしています。

<strong>出会い系サイトでの最初のチャットボットの出現</strong>
かつての出会い系サイトでは、ユーザー同士がメールやチャットを通して運命のパートナーとの出会いのチャンスを得ていたものです。しかし最近では人工知能の発達により、人間の代わりになってパートナー探しをしてくれるチャットボットが注目されています。
出会い系サイトで初めてチャットボットとして登場したのが「Lara」。2016年にフランスで誕生して以来、イギリスやヨーロッパ中に展開。日本では出会いサイトが2019年に導入したチャットボット「KARAKURI」があります。

<strong>チャットボットが私たちと通信する方法</strong>
チャットボットは組み込まれたアプリケーションプログラムによって、人間との会話を可能にする人工知能ツールです。さまざまなデータや履歴に基づいて、ディープラーニングやマシーンラーニングによるトレーニングを繰り返しながら自然言語を獲得します。
チャットボットにはテンプレートに沿って会話をするシナリオ型と、情報データを繰り返し学習しながらフレキシブルな対応ができる<a href="https://qiita.com/savaniased/items/7e66a0b76b1e20327868">AI</a>型があります。出会いサイトの<a href="https://www.romancetrain.jp/">romancetrain.jp</a>など人間の心理を解する必要がある場合は、型にはまったシナリオ型でなく個人に適切な回答が出せるAI型が有効です。

<strong>出会い系サービスで人工知能機能がどのように使用されるか</strong>
チャットボットは人工知能によりユーザーのプロフィールデータを分析しながら、ベストマッチするパートナーのプロフィールを送信してくれます。送信されたパートナーが気に入れば、すぐにチャットをスタート。メッセージアプリのようなやりとりで、チャットボットが自然言語でやりとりをしてくれます。デートにたどり着いたときは、Google マップやユーザーのフィードバックなどからベストデートスポットを納得いくまで提案。あとはユーザー同士が実際会って、恋人としてふさわしいか決め手を打つだけです！

<strong>人工知能によるサイバーセキュリティ</strong>
コンピューターによって膨大な情報が交信される世の中で、セキュリティにおいても人工知能に大きな期待がかかっています。個人の使用パターン分析をしたり日々更新されるデータ学習をしたりしながら脅威を回避できるのも、人工知能によるサイバーセキュリティのおかげです。
人間の判断や操作では阻止できないハッカーを、常に高度なセキュリティレベルで対処します。そして人工知能が出すアラームを人間が解決することでセキュリティ強化を促進。もちろん、出会いサイトにおける個人情報もサイバーセキュリティによる保護が可能です。

<strong>まとめ</strong>!

出会いサイトで見知らぬ相手とダイレクトにコンタクトを取るのは気が引けるもの。チャットボットはそんなハードルを解決してくれるハイテクマシンです。チャットボットを上手く利用しながら、素晴らしい出会いを実現してください。
コンストラクター関数とは

一言で言うと、新しくオブジェクトを作成するための雛形
Q.どういう時に使うの？　
A.テンプレート化されたオブジェクトを生成する時に使う。 


#●要点
Person.prototype.hello = function() {
  console.log('hello' + this.name);
}

const bob = new Person('Bob', '18');
const tom = new person('Tom', '38');
##中身
Pearson { name: "Bob", age: 18 }
Pearson { name: "Tom", age: 38 }

#コンストラクタ関数の呼び出し方
bob.hello();
CentOS 8 streamのインストールがnothing provides libunistringでエラーになる

##はじめに

[この記事](https://qiita.com/lighthawk/items/af545e1ebfad63c190c3)を参考に、CentOS 8 stream のインストールを行っているときに、

```
$ sudo dnf distro-sync
```
をすると以下のエラーでインストールができない。

```
 問題: package cmake3-3.6.1-3.el6.x86_64 requires libarchive.so.14()(64bit)
, but none of the providers can be installed
  - conflicting requests
  - nothing provides liblzma.so.0()(64bit) needed by libarchive3-3.3.1-1.el6.x86_64
(インストール不可のパッケージをスキップするには、'--skip-broken' を追加してみてください または、'--nobest' を追加して、最適候補のパッケージのみを使用しないでください)
```


##解決策

[CentOSフォーラム](https://forums.centos.org/viewtopic.php?t=72752)
[Remi's RPM repository](https://rpms.remirepo.net/wizard/)
を参考にコマンドを順番に実行すると良い。

以下、コマンド。

```
$ dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
$ dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
$ dnf install yum-utils
```
↓環境によっては ***実行注意***

```
$ dnf module reset php
```
```
$ dnf module install php:remi-8.0
$ dnf update
```
↑ここでアップデートが通れば、`distro-sync`も通るようになる。
ただ、`dnf update`だけでなく`distro-sync`もしっかり行わないとインストールされていないパッケージもかなりあるので注意。


##~~解決策2~~
[teratail](https://teratail.com/questions/304916)の
>zstd.x86_64とepel-rereaseをdnf removeを用いてアンインストール

を行おうとして以下を実行した。が、そのパッケージは無いよ、と怒られてしまった。

```
$ dnf remove zstd.x86_64
```

おわり。
UIImageのContentModeについて


UIImageにはContentModeという画像の見た目を変更するプロパティがあります。


## ContentMode
 Objective-C、 Swift
 ・AspectFit
 ・AspectFill
 ・ScaleToFit
の3種類でしたが、

SwiftUIでは
・ScaleToFit()
・ScaleToFill()
の2種類に変更されています。

## ScaleToFill()
```
UIImage("拡張子を除外した画像名")
　　.resizable()
　　.ScaleToFit() 
```

## AspectFill
```
UIImage("拡張子を除外した画像名")
   .resizable()
   .scaledToFill()
```

## AspectFill + ClipToBounds
```
UIImage("拡張子を除外した画像名")
   .resizable()
   .scaledToFill()
   .frame(width: 400, height: 170)
   .clipped()
```

※ .resizable()がないと画像サイズが変更できないので必須。


## 参考
アスペクト比について(Qiita外に飛びます)
https://blog.fenrir-inc.com/jp/2011/05/uiviewcontentmode.html
VCIでできないこと　その2 VCI仕様編

この記事はVCIアドベントカレンダー2020の参加記事です

# 内容を三行で
1. できる範囲でやりたいことを実現しよう！
2. 今回はunityでの設定でできないことをご紹介します。
3. 3つに分けたので今後の記事も参考にしてね

# 敵を知り己を知れば百戦殆うからず
ネガティブなことを言うなと言われるかもしれませんが、何ができないか予め把握した上で、やりたいことを実現する方法を考えましょう。じゃないと、時間をかなり無駄にしてしまうこともあるので目を背けてはいけないと思います（百敗くらい）。ここではVCIの仕様でできないことを紹介します。前回記事[unity上の設定でできないこと](https://qiita.com/sakkinonana/items/f450b0506bde991a7c96)や、スクリプトについては別の記事で触れたいと思います。

## VCIの仕様
1. 100MB以上のVCI
2. あまりにも大量のオブジェクト（チャンクサイズオーバー）
3. プロジェクト内でのVRMとVCIの共存
4. unity標準のパーティクル
5. 1万程度以上のパーティクル（effekseer表示上限）
6. 動きの拘束
7. SpringBoneへの他のコライダーの干渉

### 100MB以上のVCI
頑張って大作VCIを作っても、TSOにアップロードできるのは100MBが上限です。アップロード時に以下のように出て弾かれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/df74f1c7-5905-1b9a-5c8e-f5b7409f3df7.png)
頑張って削って100MB以内にしてあげてください。VCIにする時点では200MBでもできてしまうので、出力しながら確認しましょう。

### あまりにも大量のオブジェクト
100MB行っていなくても、あまりにも大量のオブジェクトがあると、100MB以下でも「チャンクサイズオーバーです」と出てアップロードできないことがあります。（例：数万個の星を模したico球を含むVCIを作ろうとした。）
モデルを統合するなり、VCIを分けるなりして解消しましょう。

### プロジェクト内でのVRMとVCIの共存
最初のうちでのあるあるとして、アバターを作るvrm用セットアップと、vciを作るunivciのセットアップは共存できません。操作時にエラーが出て上手く動作しなくなるので、必ずアバターを作るプロジェクトとVCIを作るプロジェクトとは分けましょう。

### unity標準のパーティクル
初心者が始める際にunityの本で勉強してパーティクルを作ろうとしてしまいがちですが、残念ながらバーチャルキャストでのパーティクルはunityの本に乗ってるのと違います。effekseerという外部ツールで作ったパーティクルに対応しているため、unity本ではなくてeffekseerのウェブページで勉強しましょう。
バージョンが違うと結構動かなかったりするので、wikiでしっかり調べてから作りましょう。（正直wikiの記事は新古入り混じっているのでわからなければdiscordで効いてみてもいいと思います。）

### 1万程度以上のパーティクル
effekseerの表示上限が1万数千個ぐらいのところにあって、それ以上出しても表示されません。
意外にすぐに上限に達してしまうため、軌跡などは特に注意。エフェクトはCPUを使うので表示上限に行くとつよつよPCでも処理が重くなってしまいます。
また、処理の問題を抜きにしても使いすぎると順番にパーティクルが表示されなくなるので、他のVCIなどにも影響します。他人に迷惑をかけないように、寿命を設定するなり消すように心がけたほうがいいです。

### 動きの拘束
一応rigidbodyのコンストレイントは使えるのですが、三軸しかありません。また、コライダーがついていたりすると叩いたり体当りするとずれてきます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/bcfd4c66-1e6a-2969-4b3d-5e9740e6d2bd.png)

よくあるラインにスライダーがくっつくみたいなのはこのままでは実現できませんが、一工夫すれば拘束できているように作ることはできます。

### SpringBoneへの他のコライダーの干渉
スプリングボーンがつくようになりましたが、早速モフろうとすると手が突き抜けてしまいます。
公式のサンプルでもそうですが、同じアイテム内でないと鑑賞できないようです。

ですが、これには解消法があって、スプリングボーンがついているアイテムの近くに来た際に透明にしたコライダーを手に追従するようにすれば触っているかのように動かすことができます。これを設定する機能がつかないかなーと思っているんですがそのうち対応してくれないかなー。
[WordPress]「整形済みテキスト」のスクロール表示をやめて、折り返し表示にしたい

内容
---
WordPress 「整形済みテキスト」のスクロール表示をやめて、折り返し表示にしたい

対応
---
CSSを使用して長い文章を折り返します。

外観 -> カスタマイズ -> 追加CSS
から以下のCSSを追加します。

```css
.xxx-pre-wrap {
  white-space: pre-wrap;
  overflow: auto;
}
```

「整形済みテキスト」ブロックの高度な設定から、「追加 CSS クラス」に設定。

```
xxx-pre-wrap
```

参考
---
https://naoya.aja0.com/archives/879
Power Automateでスプレッドシート情報をExcelに完全同期する


# この記事で書いている内容

スプレッドシートの情報をExcelに同期させる方法です。
下記のスプレッドシートのA列をキーとしています。

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/20295fa0-a41d-6866-e66d-2e3a924efcff.png)

下記ExcelのA列(列1)をキーとして
・一致⇒更新
・スプレッドシートにのみ存在⇒行追加
・Excelにのみ存在⇒削除

という処理を行っています。

<img width="400" alt="図3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/adf4aca1-c854-052b-b785-af6fd9ebfff7.png">

# 全体フロー

ざっくりとは下記のフローで処理しています。

<img width="500" alt="図1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/ca38f779-fde9-9466-4b5e-14a3765cd1bc.png">
# 実装方法

スプレッドシート：復習行を選択
Excel：表内に存在する行を一覧表示
でデータ全てを取得します。

Excelの場合は事前にテーブルを作成していないといけないので注意ください。
その後それぞれ空の配列を用意しておきます。

![2020-12-10_21h57_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/26da864e-3b49-878e-e9f1-853d78186eb7.png)


## スプレッドシートのキーの配列を作成

空白の場合は除外したいので、条件分岐で空白と等しくない場合のみ配列に追加しています。

![2020-12-10_21h47_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/f2d41964-d500-3709-5478-93f116511803.png)

## Excelのキーの配列を作成

Excel側も同じように処理していきます。
![2020-12-10_21h59_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/aa9dcd24-7717-911f-393b-62549fc0b5d4.png)

## スプレッドシート、Excelの共通キーの配列を作成

insertsection関数を使うと2つの配列の共通したもののみにできるので、
値の式に入力します。

```
intersection(variables('excel_array'), variables('ss_array'))
```

![2020-12-10_22h02_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/b1e64604-0ca5-ac9d-e093-2314085b1c2b.png)


## 共通項の更新とスプレッドシートのみのデータの更新

上記2つの1つの配列処理の中に入れています。

① 共通項と一致する列は更新
② 共通項と一致しない 且つ 空白ではない場合は行追加

という処理を行っています。

![2020-12-10_22h04_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/6a4d6672-7200-3337-5383-05db4d65b2fd.png)


## Excelのみに入っている行の削除

最後に共通項に`含まない`という条件で正の場合に行を削除して、
完全同期させます。

![2020-12-10_22h05_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/5b558744-3667-8cfa-e57b-f1786b4a27f9.png)


# 終わりに

このデータ量で15秒ぐらいかかっているので、データ量が多くなったときに
どのぐらい処理がかかるのかは不安です。

Power Automateの実行上限とかあるのかも把握していないです。

違うロジックでもできると思いますので、この方が楽に作れるなどありましたら、
教えて頂けると嬉しいです。
Laravel-mixで親ディレクトリにデプロイする方法


Laravel-mixで親ディレクトリにデプロイする場合は、setPublicPathで出力する先を指定する。

```js
const mix = require('laravel-mix');
mix
	.setPublicPath('../../dist')
	.js('assets/js/app.js', 'js/ps/')
	.sass('assets/sass/app.scss', 'css/');

```
RubyのArrayに対するメソッドまとめ

# はじめに
rubyのarrayに対するメソッドで、普段あまり使わないメソッドをまとめてみました。

# bsearch
条件を満たす値を一つ返す

```ruby
ary = [1,2,3,4]
ary.bsearch { |n| n > 1 }
# => 2
```

# combination
引数nのサイズの組み合わせを作成する

```ruby
ary = [1,2,3,4,5]
ary.combination(2).to_a
# => [[1, 2], [1, 3], [1, 4], [1, 5], [2, 3], [2, 4], [2, 5], [3, 4], [3, 5], [4, 5]]
```

# compact
nilを削除する

```ruby
ary = [1,2,nil,4,5,nil]
ary.compact
# => [1, 2, 4, 5]
```

# cycle
配列の全ての要素に対して、引数のn回処理を行う

```ruby
ary = [1,2]
ary.cycle(2) { |x| p x }
1
2
1
2
# => nil
```

# difference
引数に渡した要素を配列から取り除く

```ruby
ary = [1,2,3,4,5,6]
ary.difference([2,4])
# => [1, 3, 5, 6]
```

# dig
ネストした要素の値を参照

```ruby
ary = ['a',[['b','c'],['d','e']]]
ary.dig(1,1,0)
# => "d"
```

# drop(n)
先頭のn個の要素を削除

```ruby
ary = [1,2,3,4,5,6,7]
ary.drop(3)
# => [4, 5, 6, 7]
```

# drop_while
ブロック内がfalseを返す要素の手間までを削除

```ruby
ary = [1,2,3,4,5,6,7]
ary.drop_while { |x| x < 3 }
# => [3, 4, 5, 6, 7]
```

# fill
要素を全て引数の値に置き換える

```ruby
ary = [1,2,3,4,5,6,7]
ary.fill(nil)
# => [nil, nil, nil, nil, nil, nil, nil]
```

# filter
ブロック内でtrueを返すもののみを残す

```ruby
ary = [1,2,3,4,5,6,7,8]
ary.filter(&:even?)
=> [2, 4, 6, 8]
```

# one?
trueを返すものが一つのみの場合にtrueを返す

```ruby
ary = [1,2,3,4,5,6]
ary.one? { |x| x.even? }
# => false
ary.one? { |x| x > 5 }
# => true
```

# permutation(n)
nサイズの順列を作成

```ruby
ary = [1,2,3,4,5,6]
ary.permutation(2).to_a
# => [[1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 1], [2, 3], [2, 4], [2, 5], [2, 6], [3, 1], [3, 2], [3, 4], [3, 5], [3, 6], [4, 1], [4, 2], [4, 3], [4, 5], [4, 6], [5, 1], [5, 2], [5, 3], [5, 4], [5, 6], [6, 1], [6, 2], [6, 3], [6, 4], [6, 5]]
```

# product
配列と引数の配列の要素をそれぞれ合わせた配列を作成する

```ruby
ary = [1,2,3,4,5]
ary.product(['a', 'b'])
# => [[1, "a"], [1, "b"], [2, "a"], [2, "b"], [3, "a"], [3, "b"], [4, "a"], [4, "b"], [5, "a"], [5, "b"]]
```


# rotate
配列の最初の要素を最後に持ってくる

```ruby
ary = [1,2,3,4,5]
ary.rotate
# => [2, 3, 4, 5, 1]
```

# sample
ランダムに値を取ってくる

```ruby
ary = [1,2,3,4,5]
ary.sample
# => 3
```

# transpose
行と列を入れ替える

```ruby
ary = [[1,2],[3,4],[5,6]]
ary.transpose
# => [[1, 3, 5], [2, 4, 6]]
```
ESP-12Fを動作させるための最小回路メモ

#ESP-12Fを別ライターで書き込みしたのち、通常動作させる環境について調べたメモ

##動作した最小回路
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221204/a02fabff-c6cc-4a0d-9a3b-fcc0308a3585.png)

3.3Vの電源につなぎ、CH_PD (EN)をVCCに,GPIO15をGNDにそれぞれ直結して、動作した。電源はACアダプタの5Vを3端子レギュレータで降圧して使用した。
何度かこの回路で試してみたが、特にエラーもなく動作した。

##推奨回路？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221204/2d9412db-e2a5-ab30-a8fc-db406eca4f7e.png)
比較的よくみる回路がこれ。プルアップ、プルダウンに10Kの抵抗を入れる。さらにRESETとGPIO0もプルアップする。
GPIO0はGNDに落として起動すると書き込みモードになる。DEV基板では書き込みボタンで接地させている。
RESETはGND時にリセットなので、プルアップする。
加えて、WIFI利用時などの電力低下による誤動作を防ぐため、VCC-GND間にコンデンサーを追加している。

##CH_PD遅延回路つき
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221204/1f9ae7e0-23b2-8155-64d9-ca4353f851a8.png)
CH_PD(EN)を電源ON後にディレイさせるとさらに動作が安定するということで、紹介されているパターン。
CH_PDをコンデンサで接地させている。
VCIでできないこと　その１ unity基本編

この記事はVCIアドベントカレンダー2020の参加記事です

# 内容を三行で
1. できる範囲でやりたいことを実現しよう！
2. 今回はunityでの設定でできないことをご紹介します。
3. 3つに分けたので今後の記事も参考にしてね

# 敵を知り己を知れば百戦殆うからず
ネガティブなことを言うなと言われるかもしれませんが、何ができないか予め把握した上で、やりたいことを実現する方法を考えましょう。じゃないと、時間をかなり無駄にしてしまうこともあるので目を背けてはいけないと思います（百敗くらい）。ここではunity上の設定でできないことを紹介します。VCIの仕様でできないことや、スクリプトについては後で別の記事で触れたいと思います。

## unity基本編
1. シェーダー芸
2. マテリアルのうちいくつかの設定
3. 光源
4. 影を黒くする
5. ベイク
6. メッシュコライダー


### シェーダー
VCIで使えるシェーダーは、Standard, unlit, Mtoonの3つだけです。筆者は初心者のうちは色々試しては出力してを繰り返して時間をたくさん無駄にしてしまいました。もちろん自作も✕です。基本的にC#を書かなければいけない系統の設定は受け付けてくれません。

### マテリアルのうちいくつかの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/ef879b80-667d-3fab-0719-9ec8bf274cde.png)
マテリアルではいくつもの設定がありますが、いれても意味のないものも結構あります。
というかunity上ではできるのにいざVCIにすると効いてなかったりするので、見えるもの全部が使えるとは思わないほうがいいです。
まず全体的に、mipmapは効いてないっぽいです。
secondary Mapsは効いてないようです。
shade colorは識者の反応からして、変わった挙動をしているよう（詳しくは「影を黒くする」の項目参照）
他にも効いてないものが結構あります。逐一確認したほうがいいでしょう

### 光源
アイテムに光源入れられません。現在は基本的に一方向のみのDirect Light（アイテムで調光可）と環境光（調整不可）しかありません。MIKU LAND GATE(beta)などで点光源が入ってたことなどはありましたが、そういう特別な場合を除いて、ユーザーが弄れるところにはおりてきてません。
もし照明効果を得たければテクスチャでやるしかありません。

### 影を黒くする
また、その調整ができないためもあってか、shadeに真っ黒を設定しても影が全然暗くなりません。
環境光は消せないため、アルベドやメタリックなどをどう調整しても影が深い黒になるようなものは作れません。もちろん影を落とすのも無理です。環境光の調光なしで将来的にベイクに対応ということなので、もしかしたらサーバーにアップロードした時点でベイクされているのかもしれません。
これが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/91e090a2-1552-fe56-e2bd-271e378988ec.png)
こうなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/ed4fec86-1236-255c-4971-25a3fd829ca2.png)
これを知らないとアップロードしたあとにやけに白くなって色の調整に四苦八苦します。指定した色は出ないし、スタジオなのに照明効果が全然使えません。
広瀬すずもびっくりです。


### ベイク
VRCと同じノリでベイクをいれたくなるかと思いますが、unityでのいわゆるベイクには対応していません。深みのある表現をしたければやはりテクスチャをなんとかしないといけないです。コチラは今後対応予定とのことで、期待して待ってます。

### メッシュコライダー
使えるコライダーは、sphere,capsule,boxだけです。メッシュコライダーは入っているとエラーが出て出力ができないです。何故か出力できないとなったらた勝手に入ったのを消し忘れたとかたまにあるので注意しましょう。
本当にあった怖いNULL

# はじめに

C++では、`NULL`は `#define NULL 0`のように定義されており、本来使うべきではないところ(ポインターに関係のないところ)でも使用できてしまいます。

C++11では`NULL`の様々な問題点を解消するために`nullptr`キーワードが導入されました。`nullptr`は整数型に暗黙変換できず、より安全です。今日では`NULL`は使うべきではありません。

なぜ`NULL`は良くないのか、過去に見た事例を振り返りながら復習してみましょう。

# NULL文字とNULLの混同

NULL文字(`'\0'`)とNULLポインター(`NULL`)は異なる概念のものですが、名前が似ているためか、混同している事例がありました。偶然にも値が一致しているので正しく動作します。

間違いの例:

```cpp
char text[256];
text[0] = NULL;
```

修正例:

```cpp
char text[256];
text[0] = '\0';
```

`nullptr`は整数型へ暗黙変換できないため、このような問題は生じません。

```cpp
char text[256];
text[0] = nullptr; // エラー
```

# 文字列オブジェクトの先頭をNULLと比較している

NULL文字と`NULL`の混同である上に、無駄にわかりにくいコードです。

間違いの例:

```cpp
const string str = ...;
if (*str.c_str() != NULL) { ... }
```

修正例:

```cpp
const std::string str = ...;
if (!str.empty()) { ... }
```

# 0とNULLの混同

整数の0と`NULL`は偶然にも値が一致しますが、異なる概念のものですから混同してはいけません。

間違いの例:

```cpp
double d = NULL;
```

修正例:

```cpp
double d = 0;
```

`nullptr`は整数型へ暗黙変換できないため、このような問題は生じません。

```cpp
double d = nullptr; // エラー
```

## falseとNULLの混同

`false`と`NULL`は偶然にも値が一致しますが、異なる概念のものですから混同してはいけません。

間違いの例:

```cpp
bool f() {
   ...
   return NULL;
}
```

修正例:

```cpp
bool f() {
   ...
   return false;
}
```

`nullptr`は整数型へ暗黙変換できないため、このような問題は生じません。

```cpp
bool f() {
    return nullptr; // エラー
}
```

# コンテナをNULLで初期化している

整数0との混同ですが、異なる勘違いが背景にあるかもしれません。

間違いの例:

```cpp
std::vector<int> v(NULL);
```

修正例:

```cpp
std::vector<int> v;
```

`nullptr`は整数型へ暗黙変換できないため、このような問題は生じません。

```cpp
std::vector<int> v(nullptr); // エラー
```

## コンストラクタは`explicit`にする

`std::vector`では起こりませんが、このとき呼び出されるコンストラクタが`explicit`でない場合は、以下のようなコードも通ってしまいます。

```cpp
MyArray arr = NULL;
```

暗黙変換を意図する場合を除き、1引数のコンストラクタは必ず`explicit`を指定しましょう。

```cpp
class MyArray{
    ...
    explicit MyArray(int){ ... }
};
MyArray a = 0; // エラー: explicitのため暗黙変換はできない
MyArray a(0);  // OK
```

# 純粋仮想関数を宣言する0とNULLの混同

どんな教科書にもおそらく載っておらず、なぜこのようなコードが書かれたのかは謎です。

間違いの例:

```cpp
virtual void f() = NULL;
```

修正例:

```cpp
virtual void f() = 0;
```

もちろん、`nullptr`であれば文法エラーとなります。

# まとめ

`nullptr`を使いましょう。

また、こうしたミスを発見するには、`NULL`を`nullptr`に置換することが効果的です。
【初心者でもわかる】文字と文字の間隔を調整する方法

#どうも7noteです。字間の調整方法について

デザインツールなどでは綺麗に見せるために字間を細かく調整する機能がついています。
実はCSSでも字間を調節することが可能です。

![left.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/4c7be0f3-7e0f-2649-ae3d-0451f293f8ed.png)
※上は通常、下が字間を調整した例。

## ソース

```index.html
<p>あいうえお</p>
```

```style.css
p {
  letter-spacing: 10px;  /* 字間を10pxに指定 */
}
```

![left.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/831aff29-00d2-895a-a843-a43449abd4dc.png)


## 文字の右側に余白ができるので、中央寄せのときズレる問題の解決方法

```style.css
p {
  text-align: center;    /* 中央寄せ */
  letter-spacing: 10px;  /* 字間を10pxに指定 */
  text-indent: 10px;     /* 字間と同じ分だけインデントで調整指定 */
}
```

![center.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/28a052b4-a873-b89e-16a4-ef2fc8532e5e.png)


※2行以上だと崩れてしまうので注意。


## 右寄せのときズレる問題の解決方法

```style.css
p {
  text-align: right;     /* 右寄せ */
}

span {
  letter-spacing: 10px;  /* 字間を10pxに指定 */
  margin-right: -10px;   /* ネガティブマージンを指定 */
}
```

![right.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/6f00ae9b-d453-51a8-7b2d-b28afc59b8bc.png)


※インライン要素にしか使えませんので注意！


## まとめ

デザインからコーディングしていると、見落としがちですが字間の調整も行なうようにしましよう。
特に見出しなどが変更されている場合が多いので、忘れてしまうと「なんかデザインと印象が違う」といった事になってしまいます。

細かいところにも気を配れるコーディングを気を付けていきたいですね。


参考：https://www.websuccess.jp/blog/archives/2443/


#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】HTML・CSSのちょいテク詰め合わせ](https://qiita.com/7note)
Visualizer起動時にWorkspaceを変更する方法

# 目次
1. はじめに
2. Visualizer V8での起動時のworkspaceの変更方法
2. Visualizer V9での起動時のworkspaceの変更方法
3. まとめ
 
# はじめに
Kony Visualizer V8ではVisualizer起動時にworkspaceを選択することができます。

![スクリーンショット 0002-12-10 20.00.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/ef6a1001-0341-21c3-8c86-f4e860ed4d4e.png)

毎回起動時に上記のダイアログが表示されるので、
煩わしい場合はチェックボックスにチェックを入れると起動時にダイアログが表示されなくなります。

![スクリーンショット 0002-12-15 20.18.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/c07da9b4-7fdb-f17e-6935-4d30668f149e.png)

しかし、一度チェックを入れてしまうと、ダイアログが表示されなくなり
起動時にworkspaceを選択できなくなります。
もう一度起動時のworkspace選択ダイアログを表示したい場合の解決策について、今回紹介します:palm_tree:

また、Kony VisualizerV9では、V8のように起動時にWorkspace選択のダイアログが表示できません。
ですが、V9起動後に表示するワークスペースを変更することができますので、その方法をご説明します。
デフォルトで表示したいワークスペースが変わった時などに参考にしてみてください:musical_note:

# Visualizer V8での起動時のworkspaceの変更方法
Kony Visualizer V8にて、**Kony Visualizer>環境設定**を開いて下さい。
![スクリーンショット 2020-12-17 11.25.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/d2f46375-4801-f65f-bac7-dbfa9468a638.png)

環境設定の**General>Startup and Shutodown>workspace**に**Prompt for workspace on startup** のチェックボックスがあります。
起動時のworkspaceを選択するダイアログを非表示にしている場合、このチェックボックスのチェックが外れています。
![workspace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/a9fda125-94b4-0d89-a6ad-df7be1c2d1aa.png)

このチェックボックスにチェックを付けると、起動時にworkspaceを選択するダイアログが表示されるようになります:sparkles:

# Visualizer V9での起動時のworkspaceの変更方法

Kony Visualizer V9のインストールしたフォルダ(デフォルトではアプリケーションフォルダ)内にあるinstall_config.jsを開いて下さい。
![スクリーンショット 0002-12-10 20.18.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/c013ce28-83ed-e821-a381-b214321cc0bc.png)

install_config.jsの**exports.workspace**にデフォルトで設定されたworkspaceのパスが記載されています。
![スクリーンショット 0002-12-10 20.07.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/d73341fe-0fcb-0940-043a-0eecf37aea2c.png)

**exports.workspace**を起動時に表示したいworkspaceのパスに変更します。
変更後KonyVisualizerV9を再起動することで**exports.workspace**に記載したパスのworkspaceが表示されるようになります。

※V9でもUI上で変更できることが分かりましたら、記事更新します！

# まとめ
V8, V9それぞれ設定は異なりますが、起動時のworkspaceはいつでも変更できます！
必要になった時に上記を参考にしていただければと思います:tada:
list初期化時の落とし穴

## 任意個のdictが入ったlistを初期化してえなぁ
どうやったらいいかな？
とりあえずこうやってみるかな

``` python
>> hoge = [{}]*5
>> hoge
 [{},{},{},{},{}]
```

できてるっぽいな？
試しになんか代入してみるかな

``` python
>>> hoge[0]["huga"] = 1919
>>> hoge
[{'huga': 1919}, {'huga': 1919}, {'huga': 1919}, {'huga': 1919}, {'huga': 1919}]
```
**は？**
### なぜこうなったか
単に同じオブジェクトの参照が複製されてlistに格納されたのでこういうことになっている
つまり全部**同じdict**ということ

例えばこうやると別のdictが入るので問題はない

``` python
>>> hoge[0] = {}
>>> hoge
[{}, {'huga': 1919}, {'huga': 1919}, {'huga': 1919}, {'huga': 1919}]
```
別のdictを生成して代入しているのでまあこうなる

## そもそも初期化する時に別のdict生成して入れたいんだが？？？
そういうときは内包表記とか使ってlistを生成してやれば良い

``` python
>>> hoge = [{"key":i} for i in range(5)]
>>> hoge
[{'key': 0}, {'key': 1}, {'key': 2}, {'key': 3}, {'key': 4}]
```

内部的にはforをぶん回して都度dictを生成しているので当然大丈夫

## 終わり
こんな感じのミスをして1日潰した
ajax通信でログイン・ログアウト(Java + Spring Boot)

ajaxの基本的な構文はググればすぐ出てきたのですが、Java + Spring Bootの組み合わせて説明してあるページがあまり見当たらなかったので備忘録として残しておきます。

こんな感じでユーザ名とパスワード入力欄があったとします。やりたいこととしては、登録されてるユーザ名とパスワードを入れてログインボタンをクリックしたら、「ようこそ{ユーザ}さん」というメッセージに変換され、ログインボタンがログアウトボタンに置換されるようにしたい。
![スクリーンショット 2020-12-10 20.49.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637360/3506489d-6378-ebf2-d3ff-13146141bc5e.png)
ログインボタン押下後↓
![スクリーンショット 2020-12-10 20.49.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637360/e40cf4ac-51f0-ce04-9031-6ba515095785.png)

1. まずフロント側のにJavascriptをこんな感じで書きます。書き方はドキュメントとかに書いてある通りです。ポイントとしては、`let jsonString`の部分でデータを取得して、それをajaxの構文の中でjsonStringifyしているところ。この`JSON.stringyfy()`Java側で扱えるデータの形にします。で、ajaxの({})の中でJava側と通信する条件を決めます。urlにはJava側のRequestMappingとかのパスを入れます。`.done`以降はJava側から通信の結果が帰ってきてからの処理です。肝心のJava側での処理はと言うと次の2番を見てください。

```js

      $(() => {
        $('#login').on('click', () => {
          let jsonString = {
            'userName': $('#userName').val(),
            'password': $('#password').val()
          };
          $.ajax({
            type: 'POST',
            url: '/tutorial/auth/login',
            data: JSON.stringify(jsonString),
            contentType: 'application/json',
            dataType: 'json'
          }).done(function (data) {　// dataにはJava側メソッドの戻り値が勝手に入る
            let user = data;
            if (jQuery.isEmptyObject(user)) { //user がいなかったら
              // なんかの処理 //
            } else {
             // なんかの処理
              login(user);
            }
          }).fail(function (data) {
            alert('Error: ajax通信に失敗しました');
          }).always(function (data) { 
            console.log("ajax通信しました");
          });
        });
　　　 function login(user) {
        // ログインボタンとログアウトボタンを切り替える処理
        // メッセージを切り替える処理
      }

```
　2. 以下のように書きました。ポイントは四つです
　
   

   
  - ポイント1. @RestControllerをクラスに付与する。 これは必ずしもつけなきゃいけないわけでは無いですが、こちらのクラスでは非同期通信を行うメソッドしか書いてないので@RestControlerにしています。もし、非同期通信と通常の遷移するデータの受け渡しを行う場合はクラスに@Controllerとメソッドに@ResponseBodyが必要です。@RestControllerの場合はメソッドの戻り値がそのままレスポンスのコンテンツになるため、メソッドに@ResponseBodyを書くかなくてOK
  - ポイント2. Gsonをインスタンスかしておく。GsonはjsonをJavaで扱えるようにするライブラリ？でdependencyを追加することで使えるようになります。

```xml
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.8.6</version>
		</dependency>
```
  - ポイント3. @RequestBodyをメソッドの引数の前に追記する。これで非同期通信で渡ってきたパラメーターを自動的に受け取ることができるようになる。で、そのパラメータを使ってユーザを探し出してくる。
  - ポイント4. `gson.toJson()` でJava側で処理するためにString型にしていたデータをJsonに戻して、返す。しかしこれは、フロント側で`JSON.Parse`してもOKのはず。あとはフロントでjQuery使って画面のボタンやメッセージを表示させたり隠したりするだけ。
 

```java
@RequestMapping("/tutorial/auth")
@RestController
public class AuthController {

  private Gson gson = new Gson();

  @Autowired
  private UserService userService;

  @Autowired
  private LoginSession loginSession;

  @PostMapping("/login")
  public String login(@RequestBody UserForm form) { // @RequestBodyを付与することによって自動的にJSONデータをJavaで扱えるようにする
    User user = userService.findUser(form.getUserName(), form.getPassword());
    return gson.toJson(user);
  }
}
```
【Laravel】オレオレログイン実装の時にログイン後の画面を直前の画面にしたい

# 背景
Laravel標準のログイン機能を使わずに認証機能を実装している環境で、ログイン後に直前画面にリダイレクトする挙動を実装したかった
もっと言うと構成がこんな感じ↓で

``` routes/web.php
Route::get('/login', 'AuthController@index')->name('login');
Route::post('/login', 'AuthController@auth')

Route::middleware('auth:web')->group(function () {
    Route::get('/home', function () {
        return view('home');
    });
}
```

こんな感じ↓のログインフローがしたかった

``` 
[GET]/home：トップページ
↓  ※未認証時にログインページへリダイレクト
[GET] /login  ：ログイン入力画面
↓
[POST]/login  ：ログイン認証
↓　※最初にアクセスしてきたページ(/home)にリダイレクト
[GET]/homeトップページ
```

# 結論
1.ログイン画面に遷移した時にリファラ情報を読み取ってセッションに書き込み
2.ログインが済んだらセッションからリファラ情報を読み取ってそこにリダイレクトすればOK

# 実装前の状態
``` AuthController.php
public function index(Request $request)
{
    // ログイン済みユーザーはRouteServiceProvider::HOMEへリダイレクト
    if (Auth::check()){
        return redirect(RouteServiceProvider::HOME);
    }

    return view('login');
}

public function auth(Request $request)
{
    //login
    Auth::login(User::find($request->id));

    //laravel defaultのルートにリダイレクト
    retun redirect(RouteServiceProvider::HOME);
}
```

こんな感じの実装をしていたとしたら

# 実装後の状態
``` AuthController.php
public function index(Request $request)
{
    // ログイン済みユーザーはRouteServiceProvider::HOMEへリダイレクト
    if (Auth::check()){
        return redirect(RouteServiceProvider::HOME);
    }

    // -------差分ここから-------
    // login画面に移る前の画面の情報をセッションに保存
    if (!strpos(url()->previous(), 'login') && (parse_url(url()->previous())['host'] === $request->getHttpHost())) session(['url.intended' => url()->previous()]);
    // -------ここまで-------
    return view('login');
}

public function auth(Request $request)
{
    //login
    Auth::login(User::find($request->id));

    // -------差分ここから-------
    //redirect
    $redirectPath = session('url.intended', RouteServiceProvider::HOME);
    return redirect($redirectPath);
    // -------ここまで-------
}
```
こうすればOK

# 解説
## 書き込み部分
```
if (!strpos(url()->previous(), 'login') && (parse_url(url()->previous())['host'] === $request->getHttpHost())) session(['url.intended' => url()->previous()]);
```

左辺の```!strpos(url()->previous(), 'login')```は
```url()->previous()```でリファラ情報を取得して
```strpos(, 'login')```で文字列の中にloginがないか、
**つまり/loginにアクセスしてくる前の画面が/loginじゃなかったかを確認**

右辺の```(parse_url(url()->previous())['host'] === $request->getHttpHost()))```は
```parse_url(url()->previous())['host']```で前の画面のホストを取得
```$request->getHttpHost()```で今のログイン画面のホストを取得
**つまり、前の画面と今の画面が同じホストか確認**

まとめると、
**/loginにアクセスしてくる前の画面が/loginじゃないかつ前の画面と今の画面が同じホストの場合、セッションに前の画面情報を書き込んでいる**

## リダイレクト部分
```
    $redirectPath = session('url.intended', RouteServiceProvider::HOME);
    return redirect($redirectPath);
```

```$redirectPath = session('url.intended', RouteServiceProvider::HOME);```
でセッションにリファラ情報があればリファラ情報を、なければデフォルトパスを$redirectPathに書き込みしている


以上。
オブジェクト指向について（一言まとめ）

# はじめに
今回は、オブジェクト指向について勉強しましたので、簡単にではありますがアウトプットします。

# オブジェクトとは
データとそれに対する処理（メソッド）をひとまとめにしたもの。

# オブジェクト指向とは
- 他人が読み書きしやすいように、ルールを守って書くプログラミングスタイル。
- クラスを使って抽象化する。
- 独立性や保守性の高いプログラムを作ることができる。

# クラスとは
- 変数やメソッドをまとめたもの、オブジェクトの設計図。
- クラスをnewして具体化したものをインスタンス。

# オブジェクト指向の特徴
1. カプセル化
2. 継承
3. ポリモーフィズム（多態性）

## カプセル化
- 必要なときだけ可視化して、それ以外は隠す（情報隠蔽）。
- publicとprivateを適切に設定すること(publicはできるだけ限定的にすべき)。

## 継承
- サブクラスがスーパークラスの特性を受け継ぐこと。

## ポリモーフィズム（多態性）
- 同じメッセージを複数のオブジェクトに送っても、それぞれ固有の処理をすること。

# おわりに
オブジェクト指向について、概念はなんとなく理解はできたのですが、意識しながらコードをかけるように頑張りたいと思います！

# 参考サイト
- [オブジェクト指向とは結局何なのか あるいはプログラミングで気をつけるべきたった一つのこと](https://qiita.com/lamrongol/items/8a339721ee20a1c81e3c)
- [オブジェクト指向と10年戦ってわかったこと](https://qiita.com/tutinoco/items/6952b01e5fc38914ec4e)
認定 Platform デベロッパー資格の更新 (Winter '21)　⇒　Lightning Web コンポーネントと Visualforce の新機能の学習

１．開発者が、ユーザに標準権限があるかどうか確認したいと考えています。この点を確認するためには、開発者がどこから Salesforce 権限をインポートする必要がありますか?
２．Salesforce はいつ、すべての Visualforce URL からのインスタンス名の削除を実施する予定ですか?
３．Lightning Web コンポーネントの項目における @track デコレータの現行の使用事例はどれですか?
４．Lightning Message Service の scope パラメータのデフォルトの動作範囲はどれですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/25f74274-0998-2fb1-96bd-0872fa18c75b.png)