OmniAICreator/Qiita-1.07M huggingface dataset:
React/Vueを利用したサービス

# 概要

SPAの代表的なフレームワークであるReactとVue(+Nuxt.js)を利用したサービスについて。

# サービス一覧（React）

- Facebook
    - 
- Yahoo Japan
    - https://www.yahoo.co.jp/
- freee
    - https://www.freee.co.jp/
- Airbnb
    - https://www.airbnb.jp/
- Kibela
    - https://kibe.la/ja
- Abeja
    - ABEJAの技術スタックを公開します(2019年11月版)
    - https://tech-blog.abeja.asia/entry/tech-stack-201911

- Backlog（ヌーラボ）
    - ヌーラボの川端が、React勉強会@福岡 vol.2 に登壇します #react_fukuoka
    - https://nulab.com/ja/blog/nulab/2019-6-5-react-fukuoka-announcement/
- Slack
    - https://slack.com/intl/ja-jp/get-started#/
- Uber
    - https://www.uber.com/jp/ja/

# Vue.js

Vue.jsを導入している国内の企業・サービス一覧
- Nintendo
    - https://my.nintendo.com/
- ZOZOテクノロジーズ
    - https://speakerdeck.com/amatsukiku/frontend-architecture-design-of-zozo
- 一休com
    - 一休.comレストランのスマートフォン検索ページがSPAになりました
    - https://user-first.ikyu.co.jp/entry/2018/10/09/080000
- Retty
    - Webサービスを支えるユーザログ基盤開発＠Retty
    - https://engineer.retty.me/entry/2018/12/01/120019
- DMM
    - DMM動画サービスの問題を解決しようとしている話（コンポーネント編）
        - https://inside.dmm.com/entry/2018/07/12/components
- Gunosy
    - 社内管理画面を Vue + Go で作る
    - https://tech.gunosy.io/entry/admin-vue-go
- マンガZERO
    - https://blog.nagisa-inc.jp/archives/2980
- ITプロパートナーズ
    - サービスの管理画面で Vue + element.ui を活用する（table編）
    - https://tech.itpropartners.jp/entry/2018/12/04/132144
- M3
    - 「レガシーアプリケーションのリニューアルにNuxt.jsで戦う」というタイトルでVue Fes Japan 2018 Reject Conferenceに登壇してきました
    - https://suzan2go.hatenablog.com/entry/2018/11/10/225810
- DeNA
    - アバター着せ替えアプリ開発におけるフロントエンド技術(Vue.js活用事例) #denatechcon
    - https://www.slideshare.net/dena_tech/vuejs-denatechcon-72603570
- Codeal
    - コデアルリニューアルと技術的なトピック
    - https://www.codeal.work/contents/archives/6448
- CoupLink
    - 弊社マッチングアプリ「CoupLink」をVue.jsでSPA化しました
    - https://tech.linkbal.co.jp/4834/
- ALIS
    - 【ALISのシステム】フロントエンドアーキテクチャ：その１
    - https://alis.to/AB2/articles/34ZkxZ1pwylQ

# Nuxt.js

- リクルートライフスタイル
    - https://speakerdeck.com/yug1224/nuxtmeetup-number-4
- note
    - noteのフロントエンドをNuxt.jsへ刷新します
    - https://note.mu/konpyu/n/n9b7bf4343514
- NoSchool
    - 【実録】WordPressサイトをAWS+Laravel+Nuxtにフルリプレイスした話（技術選定編）
    - https://qiita.com/mejileben/items/f68a50ec9164b261b9cd
- TERIYAKI 
    - Nuxtのプロダクション事例
    - https://speakerdeck.com/tameto/nuxtfalsepurodakusiyonshi-li
- LINE
    - Vue Fes Japan 2018 LINE株式会社 LunchスポンサーLT
        - https://www.slideshare.net/linecorp/vue-fes-japan-2018-line-lunchlt-121657290
    - LINEとNuxtの話
        - https://speakerdeck.com/noraesae/linetonuxtfalsehua
- RoomClip
    - RoomClip の Nuxt.js 移行の話
    - https://speakerdeck.com/keisukeponpoko/roomclip-false-nuxt-dot-js-yi-xing-falsehua-d22b54df-2c6e-46df-ae77-eb7b09d485b1
moment.jsをVue.jsで使う

### タイムスタンプを日付に変換したい
YYYY/MM/DD hh:mmの形式で欲しい
<img width="186" alt="スクリーンショット 2020-02-17 12.47.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447438/e60fc3e9-5489-36f9-87d3-4ae684e4dab8.png">

### moment.jsをインストール
```
npm install moment
```

### フィルターをつくる
```javascript:filter.js
import moment from "moment";

export const filDate = value => {
  if (value === "") {
    return "";
  }
  return moment.unix(value).format("YYYY/MM/DD HH:mm");
};

export default {
  install(vue) {
    vue.filter("filDate", filDate);

    vue.prototype.$customFilter = {
      filDate
    };
  }
};
```
main.jsに下記2文を追加して使えるようにする

```javascript
import filter from "@/plugins/filter"; //インポートする
Vue.use(filter); //使う
```

### 使ってみる
```vue
<template>
  <div class="today">
    <template v-for="temperature in temperature.todayTemperature">
      {{ temperature.time | filDate }}
    </template>
  </div>
</template>
```
### 結果
YYYY/MM/DD hh:mmの形式でとれた😊
<img width="246" alt="スクリーンショット 2020-02-17 15.45.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447438/dd31d684-4070-47c1-b7ee-274cf8508e76.png">
JavaScriptでリクエストパラメータをオブジェクトに変換する

コピペで使えます

``` javascript

function convParamToObj() {
  var search = location.search.substring(1);
  if (search) {
    return JSON.parse('{"' + decodeURI(search.replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}')
  }
  return {};
}
```

## 追記
IEに対応させる必要がなければ、 [URL.searchParams](https://developer.mozilla.org/ja/docs/Web/API/URL/searchParams) を使用すればシンプルに操作できます！

``` javascript
var params = (new URL(document.location)).searchParams;
var hoge = params.get('hoge'); // hoge
var fuga = params.get('fuga'); // fuga
```



## それぞれの説明

``` javascript

var search = location.search.substring(1);
```

``` javascript
location.search // ?hoge=hoge&fuga=fuga
location.search.substring(1) // hoge=hoge&fuga=fuga
```

リクエストパラメータを取得しています

``` javascript
return JSON.parse('{"' + decodeURI(search.replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}')
```

ここは細かく確認します

``` javascript
search.replace(/&/g, "\",\"") // すべての & を "," に置換
search.replace(/=/g, "\":\"") // すべての = を ":" に置換
search.replace(/&/g, "\",\"").replace(/=/g, "\":\"")
```

正規表現を用いて、リクエストパラメータを下記のように置換しています

hoge=hoge&fuga=fuga
:point_down:
hoge":"hoge","fuga":"fuga

``` javascript
decodeURI(search.replace(/&/g, "\",\"").replace(/=/g, "\":\""))
```

リクエストパラメータがエスケープされている場合、文字列をデコードするために[decodeURI](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/decodeURI)を使用しています

``` javascript
'{"' + decodeURI(search.replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}'
```

{" と "} で先ほどの文字列を挟むとJSONの形になりますね！
hoge":"hoge","fuga":"fuga
:point_down: 
{"hoge":"hoge","fuga":"fuga"}

``` javascript
JSON.parse('{"' + decodeURI(search.replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}')
```

最後に[JSON.parse](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)でJSONをオブジェクトに変換します

これでリクエストパラメータからオブジェクトへの変換ができました！ :clap: 

参考:
https://stackoverflow.com/questions/8648892/how-to-convert-url-parameters-to-a-javascript-object
Cisco Meraki DashBoard API使用時に"API rate limit exceeded for organization" エラーが出た時の対処法

PHPを用いてmerakiのネットワークにアクセスしているデバイスや、ユーザーの情報をWeb上に出力して、把握するためのアプリを作っているときに出たエラー

"API rate limit exceeded for organization" 

の対処法です。

###原因

複数のmeraki dashboard APIと、PHPのforeach文などを組み合わせてデータの取得を行ったりするとこのエラーが出ます。原因は、アクセスが多すぎることでした。

merakiの公式ドキュメントを読むと、組織ごとに１秒間に5回までのアクセスしか認められていないと書かれています。
https://documentation.meraki.com/zGeneral_Administration/Other_Topics/The_Cisco_Meraki_Dashboard_API

###解決策

PHPのusleep関数を用いて、APIの呼び出しごとに usleep(200000)を実行(API実行ごとに0.2秒処理を停止させる)
1秒間に5回以上APIの呼び出しが行われないようになりました。
Salesforce エンジニア初心者がハマった事・注意すべき事

仕事でSalesforce上に外部向けサイトをつくる必要がありました。
（Java経験はありましたが）Salesforceに関してはまったくの初めてだったので、ハマった事や注意すべき事をまとめていきます。

レコードタイプIDを取得する際はスキーマを使う
---
Apexからオブジェクトに対してDMLを発行する際や、ヒープやCPUサイズ等に [ガバナ制限](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_gov_limits.htm) というものが関わってくる。
これはトランザクション単位でカウントされ、これらの制限を超えるとアプリケーションエラーとなる。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33505/4d2c1f5e-b24b-44d6-7770-bfd34b9bd908.png">
（基本的にアプリケーション実行中は開発者コンソールのログから、ガバナ制限を確認しながら開発を進めた方がよい）

特に気をつける点としては、繰り返し処理内のDMLで、動的にレコードタイプを検索した上でオブジェクト参照するパターンが起こり得ると思います。
そのため、レコードタイプを検索する場合は、次のように [スキーマ](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_dynamic_describeSObject.htm) を使うことでガバナ制限を増やさずにレコードタイプIDを取得することができました。

```
public ID getRecordTypeId(String objName, String recordTypeName) {
    return Schema.getGlobalDescribe().get(objName).getDescribe().getRecordTypeInfosByDeveloperName().get(recordTypeName).getRecordTypeId();
}
```

オブジェクト削除する際の権限について
---
オブジェクトを作成・編集・削除する際は実行ユーザの権限によって大きく影響されます。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33505/3581fe46-ccad-a836-2af9-aa8326a89489.png">
権限によっては参照権限もつかないため、アプリケーション上で次のエラーが発生します。

```
first error: INSUFFICIENT_ACCESS_OR_READONLY, ...
```
この問題を解決する簡単な方法ですが、システム権限を付与してしまうことです。（ただし外部向けアプリケーションの場合は、逆に意図せずデータを書き換えてしまう可能性があるため、そのへんは留意）

```
WithoutSharing ws = new WithoutSharing();
ws.insertNewCase(newCase, dmo);

private without sharing class WithoutSharing {
    public void insertNewCase(Case newCase, Database.DMLOptions dmo) {
        database.insert(newCase, dmo);
    }
}
```
WithoutSharingクラスを継承する。


---
これからも追記予定
slim内に変数を埋め込むメモ

## railsの変数を埋め込むメモ
```
- media_type = request.host.split('.')[0]

- content_for :title do
  | テスト

- content_for :page_class do
  | テスト

- content_for :head_tags do
 　//端折る

div class="#{media_type}" //ここ
```

とあるrailsのプロジェクトで媒体ごとにclassを振り分けたかった時があったのでメモ
※（ワードプレスの各ページでclassがつくイメージ）


## まとめ
個人的メモ
忘れそうだったので記述した
Maya python でノードのアトリビュートの接続を調べるメモ

## 背景

* ノードのグラフ構造を node editor とかで確認するのがめんどい
* 特定のノードの接続状態に対して, スクリプトで一括処理とかしたい

## 方法

`pm.listConnections` で, アトリビュートの接続をリストアップできます.

`.myattr` として, アトリビュートを変数で指定できるはずですが, エラーになるようであればすべて文字列で指定するといいでしょう.

```
import pymel.core as pm

n = pm.PyNode('MyNode')
print(pm.listConnections(n.myattr))

# or
print(pm.listConnections('MyNode.myattr')
```

デフォルトでは, 入力(source)と出力(destination)の両方がリストされますので,

```
# List destinations
print(pm.listConnections('MyNode.myattr', s=False, d=True)
```

```
# List sources
print(pm.listConnections('MyNode.myattr', s=True, d=False)
```

などとして, source のみ, dest のみ, などとします.

その他オプションは,

https://download.autodesk.com/global/docs/maya2012/en_us/CommandsPython/listConnections.html

あたりのドキュメントを参照ください.

## 循環参照

ものによっては, 循環参照があるアトリビュートもあります. この場合は, とりあえずはノード名で判断とかでしょうか...

## 特定のノードに入力されうる接続をすべてリストアップする

Maya channel box の inputs/outputs のレイヤーをリストアップすればいけるか?

=> 必ずしも全部とは限らないっぽい.

https://www.programcreek.com/python/example/107799/maya.cmds.channelBox

channelBox コマンドの q=1, historyObjectList=1 でいけるようだが, うまくいかない.

https://smymk.wordpress.com/2016/01/30/channelbox-historyobjectlist%E3%81%AE%E7%96%91%E5%95%8F/
基本情報18週目(02/17週)

# 目標と結果
### 目標
- 参考書をみる。
- [基本情報技術者試験ドットコム](https://www.fe-siken.com/)を使う。
- 午後で通用する様に内容を理解する。
- 情報セキュリティの勉強をする。
- アルゴリズムの勉強

### 結果
- 午後対策講座に参加しました。
    - 表計算とCASL2
- 表計算
    - 問題文の説明と表を対応させる
    - 主要な関数
        - if
        - 垂直、水平照合
        - 表引き
        - 合計
    - 相対参照と絶対参照の動作
        - ドルマークで固定
    - マクロはアルゴリズムみたいだった
- CASL2
    - 単純な命令を組み合わせる
        - 2進数への理解が重要
            - 「XOR GR0 GR0」みたいなテクニックを知っておく
                - LDで初期化するよりも早い
        - ジャンプ命令の挙動
            - ループ構造を見つける
            - JPL, JMI, JNZ, JZE, JOV, JUMP
                - 大なり小なりで判断、ゼロかどうかで判断

# 振り返り
### Keep
- アルゴリズムの勉強

### Problem
- 記憶力というよりも思考力が問われる問題が多すぎて不安

### Try
- 表計算をメインにやっていきたいと思います。
    - 仕事でも役立ちそう。
【JavaScript】配列の取り出し・追加を行う4つのメソッド

##.shift()メソッド

.shift()は0番目のインデックスの要素を削除して、後続のインデックスの値を0番目のインデックスにシフトし、削除した値を返すメソッド。

```javascript:shift

const arr = [100,200]

console.log(arr.shift()) //配列から削除した100が返される
console.log(arr) //配列に現在ある要素は[200]

console.log(arr.shift()) //配列から削除した200が返される
console.log(arr) //0番目のインデックスの要素を削除したため、配列は空

console.log(arr.shift()) //配列から削除する要素がないためundefinedになる
```
実行結果

```
[ 200 ]
100
[]
200
[]
undefined
```

##.unshift()メソッド
.unshift()は配列の最初に 1 つ以上の要素を追加し、追加後の要素数を返すメソッド。

```javascript:unshift

const arr = [100,200,300]

console.log (arr.unshift('AAA'))//配列の最初にAAAが追加される
console.log (arr)//追加後の要素数を返す

console.log (arr.unshift('BBB','CCC'))//複数追加の場合、記載順に追加される
console.log (arr)//追加後の要素数を返す
```
実行後

```
4
[ 'AAA', 100, 200, 300 ]
6
[ 'BBB', 'CCC', 'AAA', 100, 200, 300 ]
```

##.pop()メソッド

.pop()は配列から最後の要素を取り除き、その取り除いた要素を返すメソッド。

```javascript:pop
const arr = [100,200]

console.log(arr.pop())//配列の最後の要素200が返される
console.log(arr)//配列の最後の要素を削除したため、現在ある要素は[100]

console.log(arr.pop())//配列の最後の要素100が返される
console.log(arr);//配列の最後の要素を削除したため、配列の中身は空

console.log(arr.pop())//削除する要素がないためundefinedになる
```
実行結果

```
200
[ 100 ]
100
[]
undefined
```

##.push()メソッド

配列の最後に 1 つ以上の要素を追加し、追加後の配列の要素数を返すメソッド。

```javascript
const arr = [100,200,300]

console.log(arr.push('AAA'))//配列の最後に'AAA'が追加される
console.log(arr)//追加後の配列の要素数を返す

console.log(arr.push('BBB','CCC'))//複数追加の場合、記載順に追加される
console.log(arr)//追加後の配列の要素数を返す
```
実行結果

```
4
[ 100, 200, 300, 'AAA' ]
6
[ 100, 200, 300, 'AAA', 'BBB', 'CCC' ]
```
MySQLの予約語こわい問題

# 朝からなんでかSQLとおらないなあ・・・
* とあるサービスのデータベースがMySQLなのですが、開発環境を作ろうと調子にのってMySQLのバージョンを上げました
* すると普通のSQLが通りません

```
select * from member;
```

# 小一時間ほど悩んだ挙げ句、気がついた
* https://dev.mysql.com/doc/refman/8.0/en/keywords.html
 * MEMBER; added in 8.0.17 (reserved); became nonreserved in 8.0.19

* ちなみに予約後でもバッククオートすれば大丈夫

```
select * from `member`;
```

# あの時間を返してくれ・・・
* ということで、バージョンアップはうかつにしないように・・・。
* バージョンでいったり来たりもやめてほしい
フロントエンド開発時のCORSをcors-anywhereで解決する

ローカル環境で開発をしているとAPI取得時にconsoleに以下のような内容でエラー(CORS)が発生する事があります。
`Access to XMLHttpRequest at '*****' from origin 'http://localhost/' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://*****' that is not equal to the supplied origin.`

Chromeの場合、設定で一部のセキュリティをオフにする事でCORSを無効にする事が出来るのですが、なにやら設定しても上手くいかない事が多くなってきているし、そのままブラウジングする上でセキュリティ的にも宜しくないだろうという事で開発環境でのみ動作するものを利用したくなってきました。

**cors-anywhere**
https://github.com/Rob--W/cors-anywhere

こちらを開発環境のリポジトリで`npm i cors-anywhere -D`してあげます。
そのままREADME.mdに書かれているExample通りに書いてもいいのですが、今回はvue-cliの環境で使いたかったのでその設定に基づいて書いてみます。

```js:cors.js
const corsProxy = require('cors-anywhere');
const host = process.env.VUE_APP_CORS_HOST || 'localhost';
const port = process.env.VUE_APP_CORS_PORT || 8079;

corsProxy.createServer().listen(port, host, () => {
  console.log(`Running CORS Anywhere on ${host}:${port}`);
});
```
適当な場所に上記ファイルを保存し、package.jsonのnpm scriptsに実行コマンドを書きます。

```json:package.json
{
  "scripts": {
    "corsProxy": "node -r dotenv/config npm-scripts/cors.js dotenv_config_path=./.env.development development",
    "serve": "npm run corsProxy & VUE_CLI_SERVICE_CONFIG_PATH=$PWD/config/vue.config.js vue-cli-service serve --mode development"
  }
}
```
```env:.env.development
VUE_APP_CORS_HOST=localhost
VUE_APP_CORS_PORT=8079
```

`npm-scripts/cors.js`に先ほどのファイルを保存しており、且つvue-cliで利用している環境変数を`cors.js`上で読み込むため`dotenv`を`devDependencies`にインストールしておきます。

```shell
npm i dotenv -D
```

これで `npm run serve` を実行した時にCORS対策用のリバースプロキシサーバを立ち上げてVueの開発環境も立ち上がります。

APIを呼び出す箇所では以下のように書く事でリバースプロキシサーバを介してAPIにアクセスし取得する事が出来ます。

```js:***.vue
const cors = process.env.NODE_ENV === 'development' 
  ? `http://${process.env.VUE_APP_CORS_HOST}:${process.env.VUE_APP_CORS_PORT}/` 
  : '';
// http://localhost:8079/https://********/
const path = `${cors}https://********/`;
```
MaixduinoでWi-Fiを使う

# はじめに

[Sipeed Maixduino](https://wiki.sipeed.com/en/maix/board/maixduino.html)でWi-Fiが使えない。MaixPyからは使えるけど、現在のStandard SDKではサポートされていない模様。[回路図](http://dl.sipeed.com/MAIX/HDK/Maixduino/Maixduino-4.30/Maixduino-4.30(schematic).pdf)ではIO6、IO7ピンにESP32がシリアルで接続されていることになっているのに、[最新のファームウェア](https://github.com/sipeed/Maixduino_esp32_fimware)だとATコマンドのサポートはなさそう。

# サンプル

標準MaixduinoフレームワークのWiFiEspと置き換えるライブラリーを使う。

https://github.com/fukuen/maixduino-wifiesp32-lib

使用例

https://github.com/fukuen/maixduino-webcam-demo

# 追記

ESP32のファームウェアを [EspressifのATコマンド](https://www.espressif.com/en/support/download/at) のものにすればATコマンドで使えるかも。でもSPI接続の方が速度は期待できる。
Golangのネットワーク関連ライブラリを雑多にまとめる

Golangのネットワーク関連のライブラリを自分用にざっとメモ。

# HTTPリクエストを飛ばす
簡単な方法

```go
// リクエスト
resp, _ := http.Get("http://example.com")

// そのリスポンスをprint
defer resp.Body.close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(endpoint)
```
難しい方法

```go
// request structの作成
req, _ := http.NewRequest(
    "Post",
    "https://test",
    bytes.NewBuffer([]byte("request body"),
)
// そのheaderを指定
req.Header.Add("Content-Type", "application/json")

// クライアントを初期化
var client *http.Client = &http.Client{}

// そこからリクエストを飛ばす
resp, _ := client.Do(req)

// そのリスポンスをprint
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
```

# エンドポイントURLをいじる

```go

base, _ := url.Parse("https://test/mypage/")
reference, _ := url.Parse("myPicture?a=1&b=2")
endpoint := base.ResolveReference(reference).String() // URLを結合する

// クエリパラメタの確認
req, _ := http.NewRequest("GET", endpoint)
fmt.Println(q:= req.URL.Query()) // map
fmt.Println(q.Encode()) //クエリ形式の文字列
```

# MarshalとUnmarshal

* Marshalは構造体→JSON文字列のバイト配列
* UnmarshalはJSON文字列のバイト配列→構造体

```go
type Person struct {
    Name string `json:"name"`  // Marshal時のkey名をnameに
    Age int `json:"age,string"` // Marshal時valueがstringに
    Friends int `json:omitempty` // Marshal時valueがempty(0)だと無視される
    password string `json:-`   // Marshal時無視される
}

func main() {
    b := []byte{`{"name":"John", "age":25, "nickname": "Johnny"}`}
    var p Person

    // byte文字列をPerson構造体へMarshalする (属性名はCaseInsensitive)
    if err := json.Unmarshal(b, &p); err!= nil {
        fmt.Println(err)
    }

    // Person構造体をbyte文字列へUnmarshalする
    v, err := json.Marshal(p)
    fmt.Println(string(v))
}
```

* Person構造体のカスタム(アン)マーシャルを定義。Person構造体に以下のメソッドが存在すると、`json.Marshal(Person p)`や`json.Unmarshal(b, &p)`が呼び出された際、以下が使われる。

```go
// カスタムマーシャル
func (p Persion) MarshalJSON() ([]byte, error) {
    // nameだけをマーシャル
    v, err := json.Marshal(&struct{
        Name string
    }{
        Name: "Mr." + p.Name,
    }
    return v, err
}


// カスタムアンマーシャル
func (p Person) UnMarshalJSON(b []byte) error {
    // まずPerson2という構造体を定義し、Person2でアンマーシャル
    type Person2 struct {
         Name string
   }
    var p2 Person2
    err := json.Unmarshal(b, &p2)

    // それを使いpに放り込む
    p.Name = "Mr. " + p2.Name
    return err
}
```

# HMAC(Hash-based Message Authentication Code)

## HMACの仕組み

1. 事前に`APIKey`と`SecretKey`(秘密鍵=PrivateKeyではない!!!)を発行し、その両方をクライアントサイドに保存する

2. ブラウザからサーバへ以下を送信する
 * `APIKey`
 * `バイト配列のデータ`
 * `HMAC` = SecretKeyを用いたハッシュ関数を利用して、2のデータを暗号化したもの。なお、HeaderのSignatureには、この暗号化で使用したハッシュ関数の種類を収納する。
 * `用いたハッシュ関数の種類`(SHA-1、MD5など)

3. サーバサイドでは以下の手順でデータが改竄されていないことを確認する
 1. APIKeyに対応するSecretKeyを取り出す
 2. HMACをそのSecretKeyでdecryptし、それが「データ」と一致するか確かめる



## Golangで実装

```go
// クライアントサイド
func main() {
    const apiKey = "api_key"
    const apiSecret = "api_secret"

    data = []byte("data")
    h := hmac.New(sha.New, []byte(apiSecret))
    h.Write(data)
    sign := hex.EncodeToString(h.Sum(nil))

    // これをハッシュ関数サーバへ送る
}

// サーバサイド
func Server() {
    // 受け取ったapiKeyとHMACで...
    apiSecret := DB[apiKey]
    h := hmac.New(sha256.New, []byte(apiSecret))
    h.Write(data)
    expectedMAC = hex.EncodeToString(h.Sum(nil))
 
    // これが受信したデータと一致するか確認
}
```
10万人の日本大学卒業生に捧ぐ年額1000円でGoogleクラウドを容量無制限にする裏技

容量無制限のクラウド。すごく素敵な響きですよね。
もし日本大学を卒業されていたら年額1000円でその夢のような切符が手に入ります。

#裏技の正体は[日大iクラブカード](https://www.nihon-u.ne.jp/)です。



[日大iクラブカード](https://www.nihon-u.ne.jp/)に加入するとGsuiteのアカウントがもらえるのです！
年会費が1000円のカードで無限のクラウドストレージが手に入るのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533911/7048a610-105b-7643-84d9-642b9bd899a6.png)


#シンプルにGSuiteに加入すればいいと思っているそこのあなた！
GSuiteで容量を無制限にするには、

 * 5人以上の友達が必要
 * 月額1360円（年額16320円）のプランへの加入 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533911/ed7f3430-6206-0b60-4415-8e656c93fc9c.png)

私のような友達がいない人には5人も月額1360円払ってくれるような友達を見つけるのは難しいのです！
そして年額16320円は高くて払えません。

####月額1360円払える友達が5人いない。いや、シンプルに無制限のストレージを手に入れたいあなた。
###日本大学の卒業生に生まれてきたことを感謝し[日大iクラブカード](https://www.nihon-u.ne.jp/)を申し込みましょう！

では、皆さん快適なGSuiteライフをお送りください。
Windows環境でのViperMonkeyインストールと使い方

マクロ検体の解析に便利なツールの紹介です。
ViperMonkeyはPythonベースのエミュレータで、マクロ検体を放り込んで動きをつかむことができます。

#環境構成
仮想環境：VMware fusion
ゲストOS：Windows 10 Pro
→以降のインストール手順についてはWindowsをベースにしたものになります。

#インストール手順
[Github公式](https://github.com/decalage2/ViperMonkey)のReadmeの手順を参考にインストールします。
基本的に手順の通りで問題ないかと思うのですが、若干詰まったところがありましたので同様の事象の方は参考にしてください。

なお、公式ReadmeではPythonインストールについて２通りの手順が記載されていますので２通り紹介します。

##方法①PyPyを利用したインストール（公式推奨）
PyPyを利用した方が高速で解析できるため公式推奨されているようです。
###構築手順
####1.Pypyインストール
[こちらのURL](http://pypy.org/download.html)よりPyPyをダウンロード
####2.Pipのインストールと最新化
pipの有無確認
`pypy -m pip`
（pipがない場合、インストール）
`pypy -m ensurepip`
pip最新化
`pypy -m pip install -U pip`
####3.レポジトリの取得
https://github.com/decalage2/ViperMonkey/archive/master.zip
####4.依存関係の確認
`pypy -m pip install -U -r requirements.txt`
####5.起動
下記コマンドで実行できることを確認
`pypy vmonkey.py`

###pypy版　構築のポイント
####Pypyの環境変数追加
通常のCpython等と同じように、コマンドプロンプトから直接呼び出すためには環境変数に追加する必要があります。
環境変数の追加手順についてはググってくださいませ；；

####VC runtime libraryのインストール
下記２つのライブラリが入っていないと動かないかも。
https://www.microsoft.com/ja-JP/download/details.aspx?id=52685
https://www.microsoft.com/en-us/download/confirmation.aspx?id=44266


####ERROR: Failed building wheel for cryptographyのエラー
下記のようなエラーが出る場合、多くの場合pipを最新化することで解決するようです。
  ERROR: Failed building wheel for cryptography
Failed to build cryptography
ERROR: Could not build wheels for cryptography which use PEP 517 and cannot be installed directly


##方法②CPython(一般的なPython)を利用したインストール
###構築手順
####1.Python2.7のインストール
下記サイトよりダウンロードできます。
https://www.python.org/downloads/
####2.pipが最新版であることの確認
`pip install -U pip`
####3.ViperMonkeyパッケージのインストール
`pip install -U pip`
####4.起動
`vmonkey`

###構築のポイント
すでにPython 3.8を利用している方が多いのではないかと思います。
追加で2.7をインストールして共存する場合が多いと思いますのでpipコマンドの扱いにお気をつけください。
（共存している場合は、上記コマンドの`pip`を`pip2`に置き換える）

また、今回構築の際にはじめてChoclatelyを利用してみましたが、2.7/3.8共存環境が非常にシンプルに構築できて大変便利でしたのでぜひ使ってみてくださいませ！
下記の記事が大変わかりやすかったです。
https://qiita.com/segur/items/953abf91071632fdae4c


#使い方
手元にあるPowerpointのマクロ検体で実行してみました。
`vmonkey {filepath}`　で解析可能です。（簡単！）

動的解析の結果、この検体を実行すると下記のような動作を行うようです。
１）ファイルと閉じた時に動作開始
２）ping.exeのプロセス起動
３）レジストリのRunキーを登録

最終的に出力された↓の結果を確認してみると、一致していることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102081/5ed8dd50-60ed-a825-b12a-3af564e806c4.png)

ただ、他のpowloadやemotet検体で実行してみたのですがうまく読み取れないこともあるようです。
Powershell起動して外部通信で二次検体とりにいくはずですが↓読み取れていない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102081/c9365a68-2eda-50e4-c5db-262f717c903d.png)
（設定や必要なモジュールなどアドバイスありましたらいただけると幸いです！）


以上。
プログラミングという自己表現

　私は昔、VB プログラマーだった。完全なる職業プログラマーで、言語にも作り方にもこだわりはなかったと、今にして思う。

　私の今の[職場の同僚](https://qiita.com/shinchit)に、尊敬＆信頼すべきエンジニアがいる。勉強家の彼が、ある日、就業後にもくもく会に参加してきたと言う。**もくもく会とは、エンジニア種族の個個人が集まって、ひたすらもくもくと自分の好きなプログラムを作っている会のことだ。**軽くテーマが設定されていることもあり、ハッカソンほどガチでなく、技術的な不明点があると、そっと質問出来るし、すごい孤独という訳でもないのが良いのだろう。[connpass](https://connpass.com/)というエンジニアのための勉強会プラットフォームが有名みたい。
　私はソーシャルな界隈に生息しており、会社外のコミュニティに参加してゆるい知り合いを作っていくのは嫌いではない。集まる人のソーシャル的な興味、国際協力だったり環境問題だったり子ども支援だったりという、それぞれが取り組んでいる課題意識を聞き、活動を聞き、自分の見分につなげることは多い。そんな自分だからこそ、エンジニアにも同じようなことがあるのかという興味から、何気なく聞いた。
「名刺交換とかして、友達作ったりするの？」
　彼の返答は衝撃的だった。
「もくもく会では自己紹介とかあんまりしないですね。興味は、その人が何を作りたくて何を解決しようかということ。**名前なんて飾りですよ** 」
　**名前なんて飾り！名前とは、人のアイデンティティーの根源であるはずなのに、そんなものは飾りで偉い人にはそれがわからない！**
　つまりはそれくらい、エンジニアという人たちは「何を作るか」が重要で、自分が作るもののために、もくもく会への参加など実践的な場を通じて、技術力の向上を怠らないのだ。社交術で自分自身を表現するのではなく、**作るものを磨くことで、自己表現しているのだ。**技術力の向上とは、あまり目には見えず、ユーザーインターフェースとは無関係なことも多く、素人には判りにくい。自分の名前すら捨てて、物づくりに邁進するエンジニアを、心から尊敬する。いつかはソーシャルエンジニアが増えることを支援するためにも、弊社でももくもく会を主催していきたいものだ。
　(ちなみに同僚は名前を捨てたわけではいないようです念のため)
AWS IoT Coreのコンソールからすべてのモノが消えた

# 現象
AWS IoT Coreの開発中にAWSの他のサービスのダッシュボードを行き来していたらいつの間にかIoT Coreのダッシュボード上から登録したはずのすべてのモノが消えていた。
# 何が起こっていたか
ダッシュボードを行き来するうちにAWSのリージョンが切り替わっていたため、IoT Coreのダッシュボードに戻ってきたときに登録したところと別のリージョンの情報を参照していた。
# 解決策
右上のリージョン選択で正しいリージョンを選択

# その他
びっくりしました。
WordPressでヘッダー画像とサイトアイコンを管理画面から設定できるようにする

# はじめに
汎用性の高いWordPressテーマを作ろうと思うと、ヘッダー画像とサイトアイコンも管理画面から設定できた方がいいので、その方法を書きます。
ちなみにWordPressのデフォルトのテーマ`Twenty Twenty`だと簡単に管理画面から設定できます。

# ヘッダー画像
以下のコードを`functions.php`に書くと、管理画面 > 外観 > ヘッダーから設定できるようになります。

```php:functions.php
$headerDefaults = [
    'default-image'          => '',
    'random-default'         => false,
    'width'                  => 1200,
    'height'                 => 300,
    'flex-height'            => false,
    'flex-width'             => false,
    'default-text-color'     => '',
    'header-text'            => true,
    'uploads'                => true,
];

add_theme_support( 'custom-header', $headerDefaults );

```

パラメーターの詳細は[こちら](http://wpdocs.osdn.jp/%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%98%E3%83%83%E3%83%80%E3%83%BC)

`header_image`関数を使うことによって、`header.php`など、表示したい箇所に、設定したヘッダー画像を表示することができます。


# サイトアイコン
管理画面 > 外観 > カスタマイズ > サイト基本情報から「サイトアイコン」が設定できます。
設定したサイトアイコンは`get_site_icon_url`関数を使って、表示したい場所にサイトアイコンを表示することができます。
`site_icon_url`という関数もあります。

ちなみに、デフォルトだと幅・高さともに512pxで出力されてしまうので、大きすぎる場合は、引数にサイズを入れてあげてください。

パラメーターの詳細は[こちら](https://developer.wordpress.org/reference/functions/get_site_icon_url/)
UnityエンジニアがStrategyPatternを調べるおすすめの学習過程

##概要
自分がStrategyPaternを学習した軌跡のメモです。
また忘れたときに読む用ぐらいに書きましたが役に立てば幸いです。

##対象
StrategyPaternの記事が多すぎてどれからよめば良いかわからない方
UnityでC#かけるけど、デザインパターンわからんぐらいの人

##学習手順
###①使わなかった場合の問題点把握
https://twitter.com/MinoDriven/status/1228896043435094016
https://speakerdeck.com/minodriven/kusokododong-hua-switchwen-jie-shuo
これめっちゃわかりやすいです。
Swich文をStrategyPaternにしたら仕様変更に対応できるよ～って内容の動画＋スライドです

###②ざっくり把握　IT専科　Strategy パターン
http://www.itsenka.com/contents/development/designpattern/strategy.html
初めの抽象的に書いてる部分がすごいまとまってます。サンプルを複数見た後に読むとグッときます。
なのでここではまだ理解できないで大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195953/97b88b8f-54c7-4fda-3edc-0dabc7442a11.png)


###③Unityコードサンプルで把握
https://github.com/QianMo/Unity-Design-Pattern
サンプルが２つあります。
中のサンプル２を自作したクラス図です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195953/558a8b24-45cd-bf00-d07b-11551f9fc68c.png)



###④UnityでまなぶStrategyPatern
https://techlife.supride.jp/archives/1411
ここまで読むとだいだい理解できます。

###⑤　もう一度②を読む
抽象的に書いてあるので、応用するときに気を付けなければいけない点がよくわかります。


##StrategyPaternの使いどころ
抽象的に言うと
・アルゴリズム的な処理を入れ替えたいとき

具体的に読みやすくしたいと考えるタイミングで言うと
・Swich文を読みやすいように変更

もっと具体的にいうと
・映画館の価格表
・ポケモンの技みたいな分岐の実装
textlintと任意のpresetをブラウザ向けにバンドルするツール

# アイデア

[Browser上でtextlintを実行する](https://qiita.com/georgeOsdDev@github/items/34197e63d0fad307fba6)では、バンドルされるルールは[textlint-rule-preset-mobilus](https://www.npmjs.com/package/textlint-rule-preset-mobilus)固定にしていたので、

より汎用的に任意の[preset](https://github.com/textlint/textlint/wiki/Collection-of-textlint-rule#rule-preset-list)をバンドルできるようにツール化した。

# できたもの
[textlint-bundler](https://github.com/mobilusoss/textlint-browser-runner/tree/master/packages/textlint-bundler)


#使い方


1. プロジェクトを初期化する

    `$ npm init`

2. 利用したいpresetを選択または [作成](https://textlint.github.io/docs/rule-preset.html)してインストールする。

    `$ npm install textlint-rule-preset-xxxx`

3. `package.json` に `textlint.preset`として利用する`preset`を記載する。
   このとき`xxxx` はモジュール名から `textlint-rule-preset` を省いたものを指定する。 例: `japanese`、`ja-spacing`

    
    ```json
      "textlint": {
        "preset" : "xxxx"
      }
    ```
  
4. ~~`npx textlint-bundler`~~ [npx経由ではエラー](https://github.com/mobilusoss/textlint-browser-runner/issues/36)が発生するのでインストールする

    `$ npm install textlint-bundler --save-dev`

5. `textlint-bundler`の実行

    `$ node_modules/.bin/textlint-bundler`

6. 出力例をブラウザで確認

    `$ npx http-server ./dist -o /example.html`
WordPressでコメントを強制的に承認済みとする

# はじめに
普通のWordPressのサイトであれば、管理画面のディスカッション設定の「コメント表示条件」でチェックを外せばいいのですが、マルチサイトだと面倒でそんなことできません。
という場合に、コメントが入力されたら強制的に承認済みとするコードを紹介します。

# コード
```php
add_filter('wp_insert_comment', 'force_approved_comment', 10, 2);
function force_approved_comment($commentID, $comment) {
    wp_set_comment_status($commentID, 'approve');
}

```

コメントが挿入されるときの`wp_insert_comment`フックで、強制的にコメントのステータスを承認済みにしています。
【Python】自作モジュール内でloggingする

## 概要
Pythonの自作モジュールを作成した場合、logをどのように出力したらよいのか、サンプルを作りました。

## 処理内容
sample.pyというモジュールを、main.pyから呼び出します。sample.py内でlog出力の処理を書きますが、main.pyでroot loggerが作られていないと、モジュール内のloggerは何も出力しないという挙動になります。

## ハンズオン
### モジュールを作成
モジュール内を作成します。log出力の処理を書きます。

```py:sample.py
# -*- coding:utf-8 -*-
from logging import getLogger, DEBUG, NullHandler


class Sample:
    def __init__(self):
        self._logger = getLogger(__name__)
        self._logger.addHandler(NullHandler())
        self._logger.setLevel(DEBUG)
        self._logger.propagate = True

    def main(self):
        self._logger.debug('Debug')
        self._logger.info('Info')
        self._logger.warn('Warn')
        self._logger.error('Error')
```

### root loggerを作成
main.pyで利用するためのroot loggerの定義を、my_logger.pyというファイル名で作成します。
(main.py内に以下の定義をしてもよいですが、別ファイルにしました。)

```py:my_logger.py
# -*- coding:utf-8 -*-
from logging import Formatter, handlers, StreamHandler, getLogger, DEBUG


def root_logger():
    # root loggerを取得
    logger = getLogger()

    # formatterを作成
    formatter = Formatter('%(asctime)s %(name)s %(funcName)s [%(levelname)s]: %(message)s')

    # handlerを作成しフォーマッターを設定
    handler = StreamHandler()
    handler.setFormatter(formatter)

    # loggerにhandlerを設定、イベント捕捉のためのレベルを設定
    logger.addHandler(handler)
    # log levelを設定
    logger.setLevel(DEBUG)

    return logger
```

### main.pyを作成
Sampleモジュールを呼び出すmain.pyを作成します。
以下のコメントアウトにもあるように、先程作成したmy_logger.pyを呼び出しroot loggerを作成します。

```py:main.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import my_logger
import sample
from logging import Formatter, handlers, StreamHandler, getLogger, INFO


if __name__ == '__main__':
    # root loggerを作成
    logger = my_logger.root_logger()
    logger.info('The root logger is created.')

    # モジュール呼び出し
    sample = sample.Sample()
    sample.main()
```

### 実行
main.pyを実行すると、以下のようにログが出力されます。

```shell-session
$ python main.py
2020-02-17 14:01:21,721 root <module> [INFO]: The root logger is created.
2020-02-17 14:01:21,721 sample main [DEBUG]: Debug
2020-02-17 14:01:21,721 sample main [INFO]: Info
2020-02-17 14:01:21,721 sample main [WARNING]: Warn
2020-02-17 14:01:21,721 sample main [ERROR]: Error
```

## root loggerを作成しない場合
root loggerを作成しない場合の挙動を確認します。

### main.pyを修正
main.pyのroot loggerを作成する部分をコメントアウトします。

```py:main.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import my_logger
import sample
from logging import Formatter, handlers, StreamHandler, getLogger, INFO


if __name__ == '__main__':
    # 以下をコメントアウトする。
    # logger = my_logger.root_logger()
    # logger.info('The root logger is created.')

    # モジュール呼び出し
    sample = sample.Sample()
    sample.main()
```

### 実行
main.pyを実行しても、何も出力されません。

```shell-session
$ python main.py
```

以上

## 参考
- [Pythonでloggingモジュール使ってライブラリ内でログ出力する時のまとめ](https://aoishi.hateblo.jp/entry/2017/10/09/021054)
Vue）簡単なローンシミュレーター

## 完成版
Vue勉強用
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="sphenisc" data-slug-hash="LYVNmJq" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="LYVNmJq">
  <span>See the Pen <a href="https://codepen.io/sphenisc/pen/LYVNmJq">
  LYVNmJq</a> by sphenisc (<a href="https://codepen.io/sphenisc">@sphenisc</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
年齢と年収を入力すると借入可能額を計算するだけの簡単なコードです。
Android アプリ公開時に必要な画像リソースをサックっと用意する手順まとめ

みなさん、Androidアプリ公開してますか？

自分はアプリを作るのは好きなのですが、それを公開するのにあれこれ手間をかけるのは正直好きではありません、、、

簡単な自作アプリはだいたい自分が使うためにつくっているのでそれでも問題ないといえばないのですが、ビルド環境やライブラリの依存関係その他最新の開発環境全般につねにキャッチアップしておく、というのがモチベーションの一つでもあるので、いつでも更新し、リリース出来るような環境を整えたいと思うことがままあります。

その昔、Androidがリリースされたばかりの頃は、ストアには審査なんてないし、特にリソースを追加しなくてもapkをサクッとアップロードすればOKだったのですが、世知辛い世の中になったものよのう。

と、言っていてもしょうがないので、アプリをつくったらサクッと公開するために必要なリソースを取得する手順をまとめておきます。

必要なリソース
AndroidアプリをGooogle Play Storeで公開する上で必須の画像リソースは以下3種類です。

- アイコン
- スクリーンショット
- feature graphic

### ストア用のアイコンを用意する

Google Play Storeに公開するときに、アプリ内のリソースに含まれるアイコン以外に、大きいサイズ(512*512)のアイコンをアップロードする必要があります。

こちらを作るには、アプリ内のアイコンリソースと合わせて「Android Asset Studio」を使いましょう。

[Android Asset Studio - Launcher icon generator](romannurik.github.io)


ここでは使い方の詳細は省きますが、画像や用意されているクリップアートをもとにアイコン画像が作れるツールです。

背景色や形などを選び、ダウンロードボタンでzipファイルをダウンロードすると、アプリの'res'以下に含める画像とともに"web_hi_res_512.png"という名前のファイルが含まれていて、こちらがPlay Storeにアップロードするアイコンとして使えます。

### スクリーンショットを取る

次に、アプリのスクリーンショットが最低2枚必要となります。こちらはアプリを実機もしくはエミュレータで起動し、スクリーンショットを取ればいいので一見難しいことはありません。

ところが、このスクリーンショットにはステータスバーも含まれるため、起動中の他のアプリの通知アイコンなどが写ってしまいます。ストアに公開するスクリーンショットとなると、他のアプリのアイコンが写っていていいのか、時刻が夜中だったりすると良くないんじゃないか、などいろいろと考えることが出てきてしまいます。

そんなときのために、Androidには"Demo Mode"という、ステータスバーの表示内容を自由に書き換えられる機能が用意されています。

Developer Optionを有効にした端末で、Settingsの"System -> Developer options -> System UI demo mode"でDemo ModeのON/OFFが切り替えられます。

ただし、UI上では細かな設定が出来ないことと、毎回手で操作するのも手間なので、adbを使ってCLIで実行するのがいいでしょう。

adbコマンドは以下が詳しいです。

[Demo Mode for the Android System UI](android.googlesource.com)

さて、ここではアプリの通知アイコンを消し指定のみを行って、スクリーンショットを取ることを考えましょう。

Demo Modeの設定とともに、スクリーンショットの取得までadbで行得るので、以下をtake_release_screenshot.shなどスクリプトとして保存しておくと取り直しも楽になります。

```
#!/bin/sh

adb shell settings put global sysui_demo_allowed 1
adb shell am broadcast -a com.android.systemui.demo -e command notifications -e visible false
adb exec-out screencap -p > screen.png
adb shell am broadcast -a com.android.systemui.demo -e command exit
```

### Feature Graphicを作成する

最後にFeature Graphicを作成します。Feature Graphicは1024 w x 500 hの画像で、Play Storeでオススメなどに掲載された場合に使われます。また、ストアのリンクを貼った場合にogp画像としても使われます。

そのため、アプリのユーザー獲得のためには非常に重要な画像となるのですが、そんなことよりまずは手間を最小限にして公開したくなりますよね^^

そんな方に最適なツールがこちらです。

[Android Feature Graphic Generator](www.norio.be)

文字と背景を選ぶだけで、サクッと作れます。

必須ではないリソースの"promo graphic"や"TV Banner"向けのサイズも用意されています。

#### まとめ
以上で、AndroidアプリをGoogle Play Storeで公開する際に必須となっている画像リソースを手軽に用意できます。

画像以外にも"Title", "Short Description", "Full description"が必要になりますが、こちらはhogeでもfugaでもOKなので、困ることはないでしょう。

こうしてリリースしたのが、こちらの超シンプルは時報アプリです。しっかりFeature GraphicがOGPに使われていますね！

[シンプル時報 - Apps on Google Play](play.google.com)


個人アプリを作る理由として、オリジナリティのある名前をつけたり、ビジュアル面やプロモーションまでこだわることがモチベーションとなっている方もいると思いますので、そういう場合はもちろんこだわって作るのがいいでしょう。

一方で、動くものをサクッとつくって公開したい、というようなモチベーションの方はこのような方法でリリース作業にかかる負荷を下げるのがいいんじゃないかと思ってます。

アプリつくったけど公開めんどくさくて諦めた、、、って方はぜひ参考にしてみてください！
PowerShellでbash-like, zsh-likeなタブ補完

PSReadLineでのタブ補完はいくつかのモードがあります。

## Emacs-like(default)

```powershell
Set-PSReadLineKeyHandler -Key Tab -Function TabCompleteNext
Set-PSReadLineKeyHandler -Key Shift+Tab -Function TabCompleteNext
```

タブを押すと入力済みのものから補完されます。複数候補がある場合は押すたびに切り替わります。

## vi-like

```powershell
Set-PSReadLineKeyHandler -Key Tab -Function ViTabCompleteNext
Set-PSReadLineKeyHandler -Key Shift+Tab -Function ViTabCompleteNext
```

他のvi風機能を使っていないならデフォルトと同じ動作です。

## bash-like

```powershell
Set-PSReadLineKeyHandler -Key Tab -Function Complete
```

候補が一つならば、タブを押すと入力済みのものから補完されます。
複数候補がある場合は使用可能なコマンドの一覧が表示されます。

## zsh-like

```powershell
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
```

候補が一つならば、タブを押すと入力済みのものから補完されます。
複数候補がある場合は使用可能なコマンドの一覧を表示しつつ順に補完されます。
【MySQL】Windows7にインストールしてみる

PostgreSQLは既に利用しているのですが、MySQLも利用してみたいと思ったので、インストールしてみようと思いました。

# MySQLのインストール方法

## インストーラーをダウンロード
[公式のダウンロードページ](https://www.mysql.com/downloads/)からダウンロードします。
ページの下部に有る[MySQL Community (GPL) Downloads »](https://dev.mysql.com/downloads/)を選択してください。
[MySQL Community Server](https://dev.mysql.com/downloads/mysql/)を選択してください。

[下記の画像部分](https://dev.mysql.com/downloads/windows/installer/8.0.html)をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/46d8c924-d45e-7d10-7bd8-2a272b38fa3d.png)
[mysql-installer-community-8.0.19.0.msi](https://dev.mysql.com/downloads/file/?id=492815)をダウンロードしてください。

## インストーラーでの操作
ダウンロードしたインストーラーを起動してください。
### Choosing a Setup Type
通常は`Developer Default`を選択し、インストールすればいいのですが、今回は、`Custom`を選択してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/3ef16501-9e87-059f-f1ba-87c280e9995d.png)


### Select Products and Features
今回は下記のツールを選択しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/618c2972-f39b-22cd-1215-e7005a348992.png)

#### パスの変更
下記の設定を選択し、インストールするパスを変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/a5518161-e29e-4537-ff97-9a05b94fe2ed.png)

### Installation
`Execute`ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/e99bae30-6bd2-2ae1-1fa1-908df54825cd.png)
完了したら、次に進みます。

### Product Configuration
次へをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/06e09b95-829e-5fa5-5cfa-67fbb2d49a01.png)

### MySQL Serverの設定
設定に関する公式のドキュメントは[こちら](https://dev.mysql.com/doc/mysql-installer/en/mysql-installer-workflow-server.html)
#### High Availability
今回、高可用性は不要なので、デフォルトの`Standalone MySQL Server / Classic MySQL Replication`を選択しました。

#### Type and Networking
デフォルトの設定を使用します。

#### Authentication Method
デフォルトの設定を使用します。

#### Accounts and Roles
MySQL Root Passwordを設定します。
必要であればUserアカウントを登録してください。

#### Windows Service
デフォルトの設定にします。

#### Apply Configuration
`Execute`ボタンを押下します。
設定が終了したら、`Finish`を押します。

### MySQL Routerの設定
設定に関する公式のドキュメントは[こちら](https://dev.mysql.com/doc/mysql-installer/en/mysql-installer-workflow-nonserver-products.html)

#### MySQL Router Configuration
今回は、Inno DBを利用していないので、チェックをつけずに`Finish`をクリックします。

## Installation Complete
`Finish`をクリックします。

# PATHの設定を行う
コマンドプロンプトで利用できるようにするために環境変数を設定します。
## パスを探す
インストールした`MySQL\MySQL Server 8.0\bin`のパスを探します。
## 環境変数に設定
スタートメニューを押して`env`と検索し、環境変数を設定する。

**ユーザー環境変数**の部分のpathを選択し、`編集`をクリックする

「変数値」の内容に`;D:\MySQL\MySQL Server 8.0\bin`（先ほど探したパス）を追加します。
パスの区切り文字は`;`なので忘れずに付加してください。

## 動作の確認
スタートメニューで`cmd`と検索し、コマンドプロンプトを開きます。
下記のコマンドを実行し、結果が得られたら、正常に動作しています。
`mysql --version`


# 参考にしたページ
[Windows 版 MySQL インストール手順](https://qiita.com/ryo-sato/items/bd026f5e627a746f1734)
macbookair13インチ2015を広い画面で使ってみたかった。WUXGA風(1920x1200)とWSXGA+風(1680x1050)

##macbookair13インチを広い画面で使いたい
そろそろ買い替えを考えている私のmacbookair(2015)
コードを書くわけでもなく、ただのメモ＆検索用端末と化しているけれども
たまに感じる唯一の不満
「画面が狭い...」
この不満をgoogle様にぶつけてみたら
なにやらタダで疑似解像度を追加して無理やり広くする方法があるとお告げを受けた

##やってみる
参考にさせていただいた素晴らしいサイト様の情報に基づいて

`Macintosh HD -> システム -> ライブラリ-> Displays -> Contents -> Resources -> Overrides -> DisplayVendorID-610 -> DisplayProductID-9cf0`

を編集
arrayタグの中に以下をおまじない的に追加してみる

```text:DisplayProductID-9cf0
<data>AAANIAAACDQAAAAB</data>
<data>AAAPAAAACWAAAAAB</data>
```

ちょっとワクワクしながら再起動
3360x2100
3840x2400
．．．:innocent:？
凄まじい解像度が増えている？？:thinking:

##どうしてこうなった？

あの追加した文字列は１６進数をbase64エンコードしたもので
その16進数がまんまディスプレイの解像度になっているとか、いないとか...

真実を確認するために変換してみる

```text:おまじない１の文字列
AAANIAAACDQAAAAB
↓16進変換
00000D200000083400000001
↓８桁ごとに分解
00000D20 00000834 00000001
↓１つ目と２つ目を１０進にすると
3360x2100
```

````text:おまじない２の文字列
AAAPAAAACWAAAAAB
↓16進変換
00000D20 00000834 00000001
↓
3840x2400
```

追加された解像度と一致した。

##追加すべき文字列を作ってみる

````text:欲しい解像度１：1680x1050
1680は16進数で690、1050は16進数で41a
↓最後の1はフラグっぽいのでそのまま付けてみる
00000690 0000041a 00000001
↓Base64変換
AAAGkAAABBoAAAAB
```
````text:欲しい解像度２：1920x1200
1920は16進で7bc、1200は4b0
↓
000007bc 000004b0 00000001
↓Base64変換
AAAHgAAABLAAAAAB
```

arrayタグの中に追加すべきだった本当の文字列

```text:DisplayProductID-9cf0
<data>AAAGkAAABBoAAAAB</data>
<data>AAAHgAAABLAAAAAB</data>
```

追加、再起動後
無事、1920x1200と1660x1050が追加された
解像度追加したい欲求が満たされた！


##参考にさせていただいた素晴らしいサイト様
https://ji0vwl.net/index.php/2017/01/15/766/
https://ji0vwl.net/index.php/2019/10/19/2582/
https://ameblo.jp/jochi-masaharu/entry-12041077596.html
Lambda内からcloudfrontへのaxiosリクエストが403になる

ニッチなネタですが、同じくお困りの方がいらっしゃったらご参考にどうぞ

## アーキテクチャ
```
cloudfront -> api gateway -> lambda(nuxt)
```

この環境で

```
nuxt(axios) -> (out bounds) -> HTTP API(cloudfront)
```

このようにaxiosを利用して外部のサービスで、そのサービスがcloudfrontを利用している場合、その通信は403となり失敗します。

## 原因
axiosでリクエストする際に付与しているヘッダー情報に原因がありました。
`via`です。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Via

これはcloudfrontで付与されて、そのままapi gateway、lambdaへと引き継がれ、axiosのデフォルトヘッダーに設定されていました。

## 改善
cloudfrontでは多段構成を禁止する仕組みとしてこのviaを利用しているようで、このヘッダーを消すことで無事疎通が可能となりました。

```ts:nuxt(plugins)
export default ({ $axios }: Context) => {
  $axios.defaults.headers.common = {}
}
```
※この例では初期設定値をすべて消しています。
Azure Search + Java Apache HttpClient で POSTリクエストによる検索


#公式ドキュメント

Search Documents (Azure Cognitive Search REST API)
https://docs.microsoft.com/en-us/rest/api/searchservice/Search-Documents

#結論

POSTリクエストのときはURLが違うというところに少しハマりました。


#コード


```java

package hello;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.google.gson.JsonObject;

public class HelloAzurePostSearch {

	public static void main(String[] args) throws Exception {

// 公式ドキュメント
// https://docs.microsoft.com/en-us/rest/api/searchservice/Search-Documents

// POST https://[service name].search.windows.net/indexes/[index name]/docs/search
//		?api-version=[api-version]
//	  Content-Type: application/json  
//		  api-key: [admin or query key]

		String serviceName = "{your service name}";
		String indexName = "{your index name}";
		String apiVersion = "2019-05-06";

		String adminKey = "{your admin key}";

		URIBuilder builder = new URIBuilder("https://" + serviceName + ".search.windows.net" //
				+ "/indexes/" + indexName + "/docs" //
				+ "/search" // ←GETとPOSTでURLが異なる点に注意！
		) //
				.addParameter("api-version", apiVersion);

		JsonObject requestBody = new JsonObject();
		{
			requestBody.addProperty("search", "*");
			requestBody.addProperty("count", true);
		}

		CloseableHttpClient client = HttpClients.createDefault();

		HttpPost httpPost = new HttpPost(builder.build());
		httpPost.addHeader("api-key", adminKey);

		StringEntity requestEntity //
				= new StringEntity(requestBody.toString(), ContentType.APPLICATION_JSON);

		httpPost.setEntity(requestEntity);

		CloseableHttpResponse response = client.execute(httpPost);

		System.err.println(response.getStatusLine().getStatusCode());

		// response body
		System.err.println(EntityUtils.toString(response.getEntity()));

		client.close();

	}

}


```

##以上
Microsoft Teams と RPA との会話のシナリオを考えてみる

# 概要
以下の2つの記事で、チャットのフロントエンドユーザーインターフェイスであるMicrosoft Teamsと、バックエンドのRPA (Automation Anywhereを想定しているが本質的にはどんなRPAでもよい) を使った、リアルタイムでロボットが人間と会話をして判断を下すシナリオの可能性について、実装方法を検討しました。

* 『[RPAとの会話をMicrosoft Teamsに集約するしくみを作成してみた (Automation Anywhere v11編)](https://qiita.com/RPAbot/items/f4d1c1bc7f43a2a2354d)』
* 『[Azure FunctionsでMS TeamsからRPAへの会話を仲介するウェブサービスを作成してみた](https://qiita.com/RPAbot/items/3c0f5937c8e40bf7f99b)』

ただし、TeamsのWebhookによるシナリオは、必ずしもすべてのチャットのシナリオに対応しているわけではないので、利用できるシーン、シナリオが限定されてきます。この記事では、Teams Webhookを使った実装で実現できる業務シナリオのタイプについて検討します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/8b311d14-7161-822e-8923-8ac3d4a78485.png)

# 想定できるシナリオ/想定できないシナリオ

Microsoft TeamsのWebhookは、「チーム」の中に設定された「チャンネル」宛にメッセージを送信できる仕組みです。このチャンネルはあらかじめ作成しておき、ひとり、または複数のユーザーをチャンネル内に含めておく必要があります。したがって、以下のような使い方が想定されます。

### 想定シナリオ
あらかじめ決められたメンバーにRPAからの相談に対して応答する場合。応答するメンバーはチャンネルに登録されているメンバーの誰でもいい。(特定のひとりに限定したい場合は、チャンネルにはひとりだけユーザーを登録しておく。) このような場合はたとえば以下のようなシナリオが想定されます。

* RPAが操作しているシステムでエラーが出た場合に、RPAの監督者に対して作業を進めるかどうかのYes/NoのエスカレーションをRPAが行う。(いままではRPAが動作しているPC上でのYes/No確認、もしくはメール等でエラー発生の通知 & 異常終了のみが可能でした)
* AIシステムで計算された回答の確度が一定の閾値よりも低い場合に、チャンネルに登録された人間ユーザーにエスカレーションしてYes/Noまたは文章による返信を求める。(AIシステムを外部から操作できるAPIがなく、人間が画面操作でエスカレーションする必要があった)


### 想定できないシナリオ
一方、以下のような使い方はできないと理解しています。

* 個人またはアドホックに作成されたプライベートグループへのチャット送信[^1]
* メンション ("@")のついたメッセージによる通知
* チャンネルに複数ユーザーが登録されている場合、どのユーザーがチャットに応答してボタンを押したかを確認する

そのため、以下のようなケースでは対応が難しくなる可能性があります。いっそのこと、Microsoft TeamsクライアントをRPAで操作して人と同じアカウントとして対応すればできるかもしれません。(その場合はソフトウェアの利用規約も考慮しなければならなくなってくる可能性がありますが)

* 組織内の不特定のユーザーまたはユーザーのグループにメッセージを送る必要がある場合
* 応答する個人を特定する必要がある場合 (どこまで厳密に特定する必要があるかにもよる)
* リアルタイムでのコミュニケーションが必要ない場合 (これはそもそもチャットでなくてよい)

# まとめ
想定できる/できないシナリオについてざっと考えてまとめてみましたが、考えが至っていないところもあると思いますので、お気づきの点があればコメント欄にご意見ください。


[^1]: これはTeamsに限らず[LINE Chatbot](https://developers.line.biz/ja/docs/messaging-api/overview/#messaging-api%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF)などの他のプラットフォームでも同様(なはず)です。プライベートメッセージへの応答がAPIで自由にできてしまうと、お互いのプラットフォームの相互運用性を確保する仕組みができてしまい、たとえばTeamsとLINEの個人が自由にお互いにメッセージをやりとりできるようになってしまって、各プラットフォームが強みとしている、ユーザーを囲い込んでいる意味がなくなってしまうためです。
DockerのBuild Cacheの削除

Dockerfileのbuildをしていると`no space left`なるエラーが発生してしまいました。
`docker system df`でDockerが使っているストレージ容量を確認したところBuild cacheがやたらに大きいことが判明。

```bash
$ docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              25                  6                   99.35GB             74.17GB (74%)
Containers          8                   6                   27.06GB             6.004GB (22%)
Local Volumes       3                   1                   0B                  0B
Build Cache         214                 0                   41.58GB             41.58GB

```

このBuild cahcheのクリア方法がすぐに分からなかったのでメモとして残しておきます。
結論としては非常に簡単で、次のコマンドで消せます([参考URL](https://docs.docker.com/engine/reference/commandline/builder_prune/))。

```bash
$ docker builder prune
```

このコマンド実行後、`docker system df`をしてみると...

```bash
$ docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              25                  6                   99.35GB             74.17GB (74%)
Containers          8                   6                   27.06GB             6.004GB (22%)
Local Volumes       3                   1                   0B                  0B
Build Cache         96                  0                   0B                  0B
```

無事に消せました。
Dockerを使っていてストレージの残り容量に困っている方は試してみる価値があるのではないでしょうか。
pytorch3d 動作確認時メモ


pytorch3dの動作確認です

#環境

Ubuntu 18.04 LST
GPU RTX2080Ti
CUDA 10.1 
miniconda 4.7.12


#環境構築
https://github.com/facebookresearch/pytorch3d/blob/master/INSTALL.md
インストールガイドに沿って環境構築を行いました


git clone 

```
git clone https://github.com/facebookresearch/pytorch3d.git
```

conda 環境作成


```
conda create -n pytorch3d python=3.6
conda activate pytorch3d
conda install -c pytorch pytorch torchvision cudatoolkit=10.0
conda install -c conda-forge -c fvcore fvcore
```

condaでcuda10.0環境を改めて構築する

デモ用環境の構築


```
pip install scikit-image matplotlib imageio
conda install jupyter
pip install black isort flake8
```


pytorch3d本体の環境構築

```
conda install pytorch3d -c pytorch3d
```

#demo実行

notebookを起動させます

```
cd ./pytorch3d
jupyter-notebook
```
このnotebook自体では毎回pytorch3dをビルドするのでそこそこ実行時間がかかります
./docs/tutorials内にあるbundle_adjustment.ipynbをnotebookで順次実行していきます


こんな感じで推論されたカメラ角度が出力されるはずです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232732/7015f43f-5e5b-2ed6-e3e3-a44b71231f81.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232732/7ed23f77-338e-f241-7d43-703a469164d2.png)
Pythonでファイルの容量を調べるプログラムを作った

#はじめに
今回もPythonの練習のために作りました。

#ソフトウェアの説明
設定した容量以上の容量を持つファイルの絶対パスとサイズをターミナルで出力します。
オプションは以下の通り

- --start: ファイル探索のスタート地点を設定できる
- --sort: サイズの大きいファイルから出力されるようになる
- --more: 出力の基準となる容量をを設定できる
- --grep: 指定した文字列を含むパスのみ表示することができる
 

#環境
Ubuntu18.04LTS
Python3.6.9
vim

#ソースコード

```python
import argparse
import os


class Measure:
    def __init__(self, sort=None, more=None, grep=None):
        self.sort = sort

        if more is None:
            self.more = 1024 * 1024
        else:
            self.more = more

        self.grep = grep
        self.result = []

    def get_list(self):
        path_list = []
        dir_list = []
        for content in os.listdir():
            if os.path.isfile(content):
                path_list.append(content)
            elif os.path.isdir(content):
                dir_list.append(content)

        return path_list, dir_list

    def measure(self, path_list):
        for path in path_list:
            if os.path.getsize(path) > self.more:
                self.result.append(
                        (os.path.abspath(path), os.path.getsize(path))
                    )

    def get_deeper(self, dir_list):
        for dire in dir_list:
            if os.path.islink(dire):
                continue
            os.chdir(dire)
            self.main()
            os.chdir('../')

    def main(self):
        path_list, dir_list = self.get_list()
        self.measure(path_list)
        self.get_deeper(dir_list)

    def search(self, word):
        for i in self.grep:
            if word.find(i) >= 0:
                return word
            else:
                return
    
    def convert_unit(self, capacity):
        unit = {0: 'B', 1: 'KB', 2: 'MB', 3: 'GB', 4: 'TB'}
        count = 0
        while capacity // 1024:
            capacity /= 1024
            count += 1

        capacity = round(capacity)
        capacity = str(capacity) + unit[count]
        return capacity 

    def show_result(self):
        if self.sort:
            self.result = sorted(self.result, key=lambda z: z[1], reverse=True)
        for path, capacity in self.result:
            if self.grep:
                path = self.search(path)
            if path is None:
                continue
            capacity = self.convert_unit(capacity)
            print(path, capacity)


def get_parser():
    parser = argparse.ArgumentParser(description='search file\'s capacity')

    parser.add_argument('--start', help='')
    parser.add_argument('--sort', action='store_true', help='')
    parser.add_argument('--more', type=int, help='')
    parser.add_argument('--grep', nargs='*', help='')

    return parser.parse_args()


def cli():
    args = get_parser()

    if args.start:
        try:
            os.chdir(args.start)
        except FileNotFoundError:
            print(args.start , 'is not file or directory.')
            return

    m = Measure(args.sort, more=args.more, grep=args.grep)
    m.main()
    m.show_result()


if __name__ == '__main__':
    cli()
```

#おわりに
ファイルの最終更新日を表示する機能や結果をCSVファイルに保存する機能など、随時いろんな機能を追加しようと思います。