OmniAICreator/Qiita-1.07M huggingface dataset:
Amazon Honeycodeを触ってみた

## Honeycodeをさわってみた
ネットニュースでAWSがHoneyCodeなるもののBeta版をリリースしたとのこと。

>コードを記述せずにウェブ & モバイルアプリを構築する

どうやら最近流行りのノンコード・ローコード開発ツールっぽい。
私自身、コードを書くのが好きとはいえこういった最新っぽいものが出てくるととりあえず触ってみたくなる。
ということで触ってみた。

## 準備
準備といったってたいした操作は必要ない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/cdddccc0-54fc-2438-f3ca-54e4afb5b4ba.png)
AWSコンソールからHoneyCodeと調べればHitするのでクリックして進めるだけ
アカウント登録だけ必要だったので適当にぽちぽち。

ログインするとこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/b666f124-b3cf-2964-f0f4-5fce9842e314.png)

## テンプレートから作ってみる
いくつか標準的なテンプレートが用意されているみたいだったので、Simple-ToDoを使ってみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/a21faf1c-b7ca-c7c0-fe73-2be39eaf5728.png)

## それっぽいのができている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/ed2baf70-476f-1f3e-642a-0a969695ba75.png)

## Edit画面
これがEdit画面。Excel、というかMSOfficeっぽいUI。（Googleスプレッドシートとかのほうが近いかもしれない）これは確かに非エンジニアの人でもアレルギーを起こしにくい。

オレンジの枠　->　Mobile版とWeb版のアプリを切り替えられる（同時開発できるってすげー）
緑の枠　->　アプリの画面切り替え
赤い枠　->　UI、ロジック、データの3層を切り替えられる。（これが結構面白いのでさらに解説）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/71a9bd47-e903-3cfe-6277-2b24cde3cacd.png)

UI・・・いわゆる画面の見た目のところ。上の画像に見えてるのがUIのEdit画面（Builderと呼ばれる）
データ・・・Webアプリで利用するデータを管理する。ややこしいRDBを触る必要がなくて完全にエクセルライクでデータを管理できる（Tablesと呼ばれる）
ロジック・・・アプリの中で必要になる業務ロジックを記載できる（Automationsと呼ばれる）

データの管理画面（Tables）。こんな感じでRDBを触らずにWebアプリのデータを管理できる。BuilderではこのTablesから表名、列名を参照する形になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/28a4ff58-93ba-8587-96b9-6b363974b8ea.png)

ロジックの管理画面（Automations）。こ、、このUIは・・・P〇werAutomate…!?
PowerAutomateに限らず、例えばZapierなんかとも似ているUIですね。ロジックの管理画面であっても決してコードを意識させない徹底ぶり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646573/9cc6335c-e6cf-657d-e614-2bf4fe2ca3f8.png)

## さわってみて
これで何か業務アプリをノーコード開発するか？…といわれると閉口するしかないが（案件がないだけで使いどころはあるはず）
ただ、Tables,Builder,Automationという3層でUI、ロジック、データというWebアプリの3要素を見事に、かつ非エンジニアにも直感的に理解できるようにまとめている点には感動した
機会があればぜひ、それなりに使えるアプリを組んでみたい。
これくらいは知っておかないとまずいGitコマンド

#1.目的
転職してから初めてGitの存在を知り、超基礎レベルのコマンドは打てるようになりました。

ただ、たまに忘れるので、自分用にまとめておくことが目的。
これくらいはさすがにできないとまずいよね、という観点。

使うのはGitHubと、GitBash。

#2.よく使うコマンド

##(1)事前準備
###(ⅰ)GitのDL
下記はwindows用
https://gitforwindows.org/

###(ⅱ)GitHubへの登録
https://github.com/

###(ⅲ)GitHubへの登録その2
Git Bashから下記コマンドで、GitHubへ登録したusernameとメールアドレスを登録する

```
$git config --global user.name"××××"
$git config --global user.email"△△△△"
```

##(2)コマンド集
基本的に時系列に沿って書いていきます。

###●今いるディレクトリを確認
```
$ pwd
```

###●ディレクトリの変更
```
$ cd　変更したい場所
```

###●今いるディレクトリ内にあるファイルを確認
```
$ ls
```

隠れファイルといった全てのファイルを確認するには下記。

```
$ ls -a
```

###●gitファイルをディレクトリ内に作成
```
$ git init
```


###●add
```
$ git add ファイル名
```

ディレクトリ内のすべてのファイルをaddする場合は下記

```
$ git add .
```

###●commit
```
$ git commit
```

※補足※
Git Bashでcommitメッセージを入力する際は、まずiを押して挿入モード
→commitメッセージを書いたら、Escキー→「:wq」→Enterを押すと画面を閉じれる

###●（コマンドではない）リポジトリの登録
GitHub上でリポジトリを作っておく

###●GitHubへのpush

まずはGitHubで作ったリポジトリをGitBash上で登録する。

```
$ git remote add origin https://github.com/●●（username）/リポジトリ名
```

GitHubへpushする

```
$ git push -u origin master
```

###●接続先のリポジトリを変更する場合

現在の接続先を確認

```
$ git remote -v
```

接続先を変更

```
$ git remote set-url origin ●●●（接続先）
```

以上。
ぼちぼち追記していきます！
[Microsoft] 1. ヒーローエディタ - Angularチュートリアル Tour of Heroes を Blazor で再実装する

# ヒーローエディタ

[雛形が出来上がりました](https://qiita.com/sengoku/items/9f4c149f92c3c53772d7)ので、ヒーロー情報を表示するコンポーネントを作成し、アプリケーション内に配置してみます。

----


# Heroesコンポーネントを作成する

dotnet cliを使ってrazorコンポーネントを作成します。

```console
dotnet new razorcomponent --output BlazorTourOfHeroes/Shared --name Heroes
```

既存の `BlazorTourOfHeroes/Shared` ディレクトリの中に `Heroes.razor` ファイルが出来上がります。

```razor:Shared/Heroes.razor
<h3>Heroes</h3>

@code {

}
```

（ @Qiita さんrazorシンタックスハイライト待ってます）


## `hero`変数を追加する

コンポーネントに`hero`変数を追加します。

```c#
    private string hero = "Windstorm";
```

## `hero`を表示する

既存のHTMLタグを消去して、`hero`変数に置き換えます。

```razor
@hero
```

# Heroesコンポーネントを表示する

Heroesコンポーネントをトップページに表示するため、`index.razor`を変更します。

```razor:Pages/Index.razor
<Heroes></Heroes>
```

# こんなんできました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/1568c405-24d1-dd9f-989c-83aaa68d594c.png)



# Heroクラスを作成する

名前以外の属性を格納するためHeroクラスを作成します。

```cs:Model/Hero.cs
namespace BlazorTourOfHeroes.Model
{
    public class Hero
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}
```

Heroesコンポーネントに戻り、作成したHeroクラスを使うようにリファクタリングします。

```razor:Shared/Heroes.razor
@using BlazorTourOfHeroes.Model

@hero

@code {
    private Hero hero = new Hero
    {
        Id = 1,
        Name = "Windstorm",
    };
}
```

# heroオブジェクトを表示する

テンプレートを変更してheroオブジェクトを表示するようにします。

```razor:Shared/Heroes.razor
<h2>@hero.Name</h2>
<div><span>id: </span>@hero.Id</div>
<div><span>name: </span>@hero.Name</div>
```

# hero名を大文字にする

大文字にするのは、`String.ToUpper()`を呼ぶだけです。

```razor:Shared/Heroes.razor
<h2>@hero.Name.ToUpper()</h2>
```

こんなんできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/80d99da2-3e6d-1d2c-c605-1ed444ff1c73.png)


# heroを編集できるようにする

`<input>`テキストボックスを用意してheroを編集できるようにします。


## バインディング

Heroesコンポーネントをリファクタリングして次のようにします。

```razor:Shared/Heroes.razor
<div><label>name: <input @bind="hero.Name" placeholder="name" /></label></div>
```

# こんなんできました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/d3eec0c9-b49c-aa87-a770-36e56694dff1.png)
[Microsoft] 新規プロジェクトの作成 - Angularチュートリアル Tour of Heroes を Blazor で再実装する

Angularの[チュートリアル: Tour of Heroes](https://angular.jp/tutorial) をBlazorを使って再実装してみます。

# 新規プロジェクトを作成する

dotnet CLIを使用して初期アプリケーションを作成します。

1. 開発環境をセットアップします。
2. ソリューションとプロジェクトを作成します。
3. サーバを起動してアプリケーションを動かしてみます。

----

# 開発環境をセットアップする

[こちらの手順](https://docs.microsoft.com/en-us/aspnet/core/blazor/get-started?view=aspnetcore-3.1&tabs=netcore-cli)に従って開発環境をセットアップします。

Macの場合は、brewを使えば一発です。

```cl
brew cask install dotnet-sdk
```

# ソリューションとプロジェクトを作成する

テスト等も含めたいので、プロジェクトを作成する前にソリューションを作成します。

```cl
dotnet new sln -o BlazorTourOfHeroes
```

ディレクトリとソリューションファイルが出来上がるので移動します。

```cl
cd BlazorTourOfHeroes
```

続いてBlazorプロジェクトとテストプロジェクトを作成します。

```cl
dotnet new blazorwasm -o BlazorTourOfHeroes
dotnet new xunit -o BlazorTourOfHeroes.Tests
```

ソリューションに作成したプロジェクトを追加します。

```cl
dotnet sln add BlazorTourOfHeroes
dotnet sln add BlazorTourOfHeroes.Tests
```

gitignoreファイルを作成します。

```cl
dotnet new gitignore
```

あとはいつものようにgitを初期化してコミットしておきます。


# サーバを起動する

サーバを起動してみます。

```cl
dotnet run -p BlazorTourOfHeroes
```

ブラウザを起動して [https://localhost:5001](https://localhost:5001) か [http://localhost:5000](http://localhost:5000) へアクセスします。


# こんなんできました

こんな感じの画面が見られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/fe646f17-161d-8ea7-c8d8-cc2504d9992c.png)



# 画面を構成するコンポーネント

以下のようなrazorファイルが生成されています。
razorファイルひとつがコンポーネントになります。
Angularのように、スタイルシートを個別に持つことはできません。

```
├── App.razor
├── Pages
│   ├── Counter.razor
│   ├── FetchData.razor
│   └── Index.razor
└── Shared
    ├── Heroes.razor
    ├── MainLayout.razor
    ├── NavMenu.razor
    └── SurveyPrompt.razor
```

`App.razor`がAngularでいうところのルーティングを担っています。




# 変更してみる

## トップページのタイトルを変更する

`Index.razor`ファイルを編集します。

```razor:Pages/Index.razor
<h1>Tour of Heroes</h1>
```

## スタイルを変更する

スタイルシートはアプリケーション全体で一つです。

```css:wwwroot/css/app.css
h1 {
    color: #369;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 250%;
}

h2, h3 {
    color: #444;
    font-family: Arial, Helvetica, sans-serif;
    font-weight: lighter;
}
```
パッケージ名からアプリ名(AndroidManifestのlabel属性のもの)を取得する

暗黙的Intentで選択したアプリ名を使いたくて、パッケージ名からアプリ名を取得する必要があったため備忘録含め以下に展開します。

[こちらのgetApplicationLabel](https://developer.android.com/reference/android/content/pm/PackageManager#getApplicationLabel(android.content.pm.ApplicationInfo))を使うと以下のようになります。
※[loadLabelでも可](https://developer.android.com/reference/android/content/pm/PackageItemInfo#loadLabel(android.content.pm.PackageManager))

なお、パッケージ名はいくつか取得方法があると思いますがいつかよく使う、URLをブラウザで開くケースを載せておきます。

```Case1.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main)
    val launchIntent = Intent(Intent.ACTION_VIEW)
    val url = "https://www.google.com/?hl=ja"
    launchIntent.data = Uri.parse(url)

    val intentPick = Intent()
    intentPick.action = Intent.ACTION_PICK_ACTIVITY
    intentPick.putExtra(Intent.EXTRA_TITLE, "Launch using")
    intentPick.putExtra(Intent.EXTRA_INTENT, launchIntent)
    startActivityForResult(intentPick, 1)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == 1) {
        val packageName = data?.component!!.packageName // パッケージ名取得方法①
        val appName = packageManager.getApplicationLabel(packageName, PackageManager.GET_META_DATA).toString()
        startActivity(data)
    }
}
```

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

    val url = "https://www.google.com/?hl=ja"
    val intent = Intent(Intent.ACTION_VIEW)
    intent.data = Uri.parse(url)
    val pendingIntent = PendingIntent.getBroadcast(
            this,
            123,
            Intent(this, ShareBroadcastReceiver::class.java),
            PendingIntent.FLAG_UPDATE_CURRENT
    )

    val chooser = Intent.createChooser(intent, null, pendingIntent.intentSender)

    button.setOnClickListener {
        if (intent.resolveActivity(packageManager) != null) {
            startActivity(chooser)
        }
    }
}

class ShareBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        val packageName2 = intent?.getParcelableExtra<ComponentName>(Intent.EXTRA_CHOSEN_COMPONENT)?.packageName // パッケージ名取得方法②
        val keys = Objects.requireNonNull(intent!!.extras)?.keySet()
        if (keys != null) {
            for (key in keys) {
                try {
                    val packageName = (intent!!.extras!![key] as ComponentName?)?.packageName// パッケージ名取得方法③
                    val packageManager: PackageManager? = context?.packageManager
                    val appName = packageManager?.getApplicationLabel(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)) as String
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
    }
}

```

上記で取得できるパッケージ名例は以下

```
com.android.chrome
org.mozilla.firefox
jp.co.fenrir.android.sleipnir
```

取得できるラベル名は以下(※必ずしもアプリ名とは一致しません)

```
Chrome
Firefox
Sleipnir
```
スクショ・画面録画されたことを通知する方法

スクリーンショットや画面録画がされたことを通知するには,その`ViewController`の中で

```Swift
override func viewWillAppear(_ animated: Bool) {

        NotificationCenter.default.addObserver(self, 
        selector: #selector(didTakeScreenshot), name:                                UIApplication.userDidTakeScreenshotNotification, object: nil)
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(didCapturedScreen),
            name: UIScreen.capturedDidChangeNotification,
            object: nil
        )
        
    }
```
`ViewDidLoad()`でも構いません。
`didTakeScreenshot`や`didCapturedScreen`自分で決める関数であるので、例えば以下のようにします。

```Swift
@objc func didTakeScreenshot() {
    print("スクリーンショット")
 }
```


必要に応じて通知を削除します。

```Swift
override func viewWillDisappear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.removeObserver(self,name: UIApplication.userDidTakeScreenshotNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIScreen.capturedDidChangeNotification, object: nil)
    }
```
VSCodeでEmmetによるインテリセンス（コード補完）が効かないとき

ググっても中々答えがなかったのでメモ。HTMLファイルではEmmetが聞くのに、Ruby on Rails で開発しているときは何が全然予測候補を出してくれなかった。結論、Emmetの対象に`.erb`が入ってなかっただけ。

https://qiita.com/Mr_ozin/items/d7fb30ed56347f6d222e

VSCodeで New File しても、ファイルを`.html`として保存していない状態だったり、右下の Language Mode を `Plain Text`のままにしててもEmmetは効かないので注意。
NotificationCenter.default.removeObserverの大切さを痛感した話

##起きたこと
<img width="200" alt="IMG_0347 2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/a819ae56-d2e9-48d3-c2c4-5bc92180965c.png"> <img width="200" alt="IMG_0343.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/5073b8f9-d926-cc4c-9273-68b14a3da3ab.png">
TableViewControllerとNavigationControllerでできているチャットアプリを作成していたところ、トーク画面でスクショすると自動送信されるメッセージが他のトーク画面でスクショしても送信されるバグが発見された。
<img width="200" alt="IMG_0331 2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/176e41b5-eca8-1621-9126-345985585a78.png">

##原因と処理

スクショの監視するObserVerを`ViewDidLoad()`の中に書いていたのですが、

```Swift
NotificationCenter.default.addObserver(self, selector: #selector(didTakeScreenshot), name: UIApplication.userDidTakeScreenshotNotification, object: nil)
```
`NavigationController`画面遷移をしたときに通知を外していないことが原因でした。

```Swift
NotificationCenter.default.removeObserver(self,name: UIApplication.userDidTakeScreenshotNotification, object: nil)
```
を`viewWillDisappear`の中で書くことで期待した処理をすることが出来ました。
npm install時のエラー解決 No Xcode or CLT version detected!

# 環境
macOS Catalina 10.15.4
npm 6.14.5

以下のエラーが出た時の解決

```.shell
No receipt for 'com.apple.pkg.CLTools_Executables' found at '/'.

No receipt for 'com.apple.pkg.DeveloperToolsCLILeo' found at '/'.

No receipt for 'com.apple.pkg.DeveloperToolsCLI' found at '/'.

gyp: No Xcode or CLT version detected!
gyp ERR! configure error
gyp ERR! stack Error: `gyp` failed with exit code: 1
gyp ERR! stack     at ChildProcess.onCpExit (/Users/izumi/.anyenv/envs/nodenv/versions/14.3.0/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:351:16)
gyp ERR! stack     at ChildProcess.emit (events.js:315:20)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:276:12)
gyp ERR! System Darwin 19.4.0
(省略)
gyp ERR! node -v v14.3.0
gyp ERR! node-gyp -v v5.1.0
gyp ERR! not ok
```

# 原因
Xcode Command Line Toolsの割当がおかしかった

```.shell
$ xcode-select -p
/Library/Developer/CommandLineTools
```

# 解決方法

Xcodeがインストール済かどうかで対処方法が変わります。

## Xcodeインストール済の場合
xcode-select -sでXcode内のCommandLineToolsにセットし直したら解決

```.shell
$ sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
$ xcode-select -p
/Applications/Xcode.app/Contents/Developer
```

## Xcode未インストールの場合
多分以下で解決するはず
(この方法実際に試せていないので解決しなかったらごめんなさい)

```.shell
$ xcode-select --install
```
SAMでS3にCSVファイルアップロードをトリガーにDynamoDBへの登録処理の作成 Lambdaの関数部分

## 概要
[前回の記事](https://qiita.com/dmikita/items/2cbc5675dac14a7d380b)のLambda関数の部分です

## Lambda
Lambda関数は以下になります

```python
import json
import boto3
import os
import csv
import codecs
import sys
import traceback
import collections
from datetime import datetime

s3 = boto3.resource('s3')
dynamodb = boto3.resource('dynamodb')

bucket = os.environ['bucket']
tableName = os.environ['table']

def lambda_handler(event, context):

   key=event['Records'][0]['s3']['object']['key']
   #get() does not store in memory
   try:
       obj = s3.Object(bucket, key).get()['Body']
   except:
       print("S3 Object could not be opened. Check environment variable. ")
       print(traceback.format_exc())
   try:
       table = dynamodb.Table(tableName)
   except:
       print("Error loading DynamoDB table. Check if table was created correctly and environment variable.")
       print(traceback.format_exc())

   batch_size = 100
   batch = []
   date =datetime.now()
   dateStr=date.strftime('%Y%m%d')

   #DictReader is a generator; not stored in memory
   for row in csv.DictReader(codecs.getreader('utf-8')(obj)):
      if len(batch) >= batch_size:
         write_to_dynamo(batch)
         batch.clear()
      batch.append(row)

   if batch:
      write_to_dynamo(batch)

   return {
      'statusCode': 200,
      'body': json.dumps('Uploaded to DynamoDB Table')
   }


def write_to_dynamo(rows):
   try:
      table = dynamodb.Table(tableName)
   except:
      print("Error loading DynamoDB table. Check if table was created correctly and environment variable.")
   try:
      with table.batch_writer() as batch:
         for i in range(len(rows)):
            row=rows[i]
            batch.put_item(
               Item=row
            )
   except:
      print(traceback.format_exc())
      print("Error executing batch_writer")

```

## ソースの説明
* BOTO3の使い方は[公式ドキュメント](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html)参照。
* コードを見ればなんとなくわかるかと思いますが、使用するリソースを指定して使用します。
    * バケット名、テーブル名は環境変数としてLambdaの定義に指定しています
    * ```key=event['Records'][0]['s3']['object']['key']``` の部分でS3にオブジェクトが格納されたときに渡されるキーを取得しています。

## 補足
* BOTO3には他のサービスを使用する機能も色々あるので必要に応じて使うとよさそうです。
* 最初は処理の中で日時をセットしたり、カラムの内容の変換を行っていましたが、Lambda内で下手に処理をやると処理時間が伸びてしまったので事前に加工できるなら加工してしまった方がよさそうです。
* 前回の記事ではDynamoDBのキャパシティーモードをプロビジョニングにしたところ大量にデータを登録するときに失敗してしまったので大量にインサートを行うときはオンデマンドの方がよさそうです。ただしお金がかかるのでお試しでやる場合はしっかりと考えた方が・・・
* DynamoDBにグローバルセカンダリーインデックスがあると余分にキャパシティを消費するのでそのあたりも実際に使う前に考えた方がよさそうです。
* 状況の確認はCloudWatchLogs で確認できるので処理に時間がかかる時はそちらで確認できます。
Makefile の Built-in ターゲット

# Built-in ターゲット

AWS Lambda Layer の実装を見ていくなかで、その実装が Makefile で書かれていた。 ちょっと公開されている内容を修正したいという事案に当たったのだが、Makefileを読んでいると、`.ONESHELL` や `.PHONY` など、どうも特別な意味を持っているような用語がでてくる。 で、書き方もターゲットのものになっているのだが、どうも普通のターゲットが意味するものとは違うような感じであった。

make コマンドの実行時でターゲットが省略されている時は、makefile の最初に書かれたターゲットが実行される、というルールがあるはずなのに、`.ONESHELL` が makefile の最初のターゲットとして定義されていて、どうもそれが実行されていなさそうだったので、特別な意味があるとは思っていた。
何故これが特別な意味を持つターゲットであり、どのような書き方なのかが分からなかったので色々と調べてみていたのだが、「Built-in ターゲット」としてドキュメントにはまとまっていた。

https://www.gnu.org/software/make/manual/make.html#Special-Built_002din-Target-Names

その他にも「疑似ターゲット」「ダミーターゲット」「特殊ターゲット」と呼ばれることもあるらしい。


## `.ONESHELL` の意味

使い方としては `.ONESHELL` ターゲットを書いておくだけで良い。
これを書いておくと、1つのターゲットの処理を1つのシェルプロセスで実行するようになる。 言い換えると、`.ONESHELL` ターゲットが定義されていない場合は1行毎に別のプロセスで処理を行うようになる。

```make:Makefile
all: sample
	echo AAA && sleep 1
	echo BBB && sleep 1

sample: 
	echo sample1 && sleep 1
	echo sample2 && sleep 1
```

上記の場合は、`echo sample1 && sleep 1` , `echo sample2 && sleep 1` , `echo AAA && sleep 1` , `echo BBB && sleep 1` の4つが順番にシェルプロセスとして実行される。　一方、

```make:Makefile
.ONESHELL:

all: sample
	echo AAA && sleep 1
	echo BBB && sleep 1

sample: 
	echo sample1 && sleep 1
	echo sample2 && sleep 1
```

として `.ONESHELL` Built-in ターゲットを宣言している場合 (宣言だけで良い)、`echo sample1 && sleep 1 && echo sample2 && sleep 1` , `echo AAA && sleep 1 && echo BBB && sleep 1` の2つのシェルプロセスが実行される。
【Android】DataBindingのvariableはcamelCaseで書く

```xml
<variable name="hoge_text" type="String">
```
より、

```xml
<variable name="hogeText" type="String">
```
のが困らないと思うっすという話。プチハマったので。

## 具体例
「被`<include>`ファイルでsnake_caseのvariableを使おうとしたらアクセスできなかった」

#### 書いてみるxml

```child.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="value_text"
            type="String" />
    </data>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{value_text}"/>
</layout>
```

```parent.xml
<親要素省略>
    <include
        layout="@layout/child"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:value_text="@{someVariable}"/>
</親要素省略>
```

#### 生成されるコード

```ChildBindingImpl.java
    public void setValueText(@Nullable java.lang.String ValueText) {
        this.mValueText = ValueText;
        synchronized(this) {
            mDirtyFlags |= 0x2L;
        }
        notifyPropertyChanged(BR.value_text);
        super.requestRebind();
    }
```

```ParentBindingImpl.java
    @Nullable
    private final app.package.name.databinding.ChildBinding mboundView;
// ~~~ 略 ~~~
            this.mboundView.setValue_text(someVariableGetValue); // <- お前ー！！
```

#### エラー内容

```error
エラー: シンボルを見つけられません
            this.mboundView3.setValue_text(someVariableGetValue);
                            ^
  シンボル:   メソッド setValue_text(String)
```

というわけで、`app:snake_case`属性により生成される関数名が、
`<variable name="snake_case">`により生成される関数名と異なるためビルドに失敗します。

「じゃあ`app:camelCase`&`<variable name="snake_case">`ならどうよ」という気もしますが、
その場合は**xmlファイル側で名前の解決が出来ず、BindingImplの生成前にエラーになる**ようです。書く側としてもxml内でその切り替えはしんどいっす。（自分の場合）

#### 対処

冒頭に書いた通りです。

```child.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="valueText"
            type="String" />
    </data>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{valueText}"/>
</layout>
```

```parent.xml
<親要素省略>
    <include
        layout="@layout/child"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:valueText="@{someVariable}"/>
</親要素省略>
```
定義からcamelCaseにしましょう。

## おまけ

あんまり明言はされてないと思うんですが、
[公式](https://developer.android.com/topic/libraries/data-binding/expressions?hl=ja)のサンプルでも２単語の変数名をさがしました。camelCaseでした。（`userList`）

```xml
    <data>
        <import type="com.example.User"/>
        <import type="java.util.List"/>
        <variable name="user" type="User"/>
        <variable name="userList" type="List&lt;User>"/>
    </data>
```

このあたり(じゃあresourceのidもcamelCaseにしとく？ とか)はGoogle提供のコードでも一貫されていない感があるので、昔から小さく話題になることみたいですね。
CSSでルビの表示位置を調節（実験メモ）

# 目的
　HTML上でrubyタグを使ってルビ（フリガナ）を振ると、ルビのある行にルビテキスト分のline-heightが確保され、ルビのない行と比べて行間が不揃いになる。
　これに対処するには本体テキストのline-heightを大きくし、ルビが入っても影響しないレベルまで行間を広げる。それは正しい対応であるが、デザイン的にはそれなりに制約となるのでどうにかしたい。
　**以下、あくまで実験です**

# 方針
- ~~本文テキストについてline-heightに対するテキストの表示位置を下げ、各行の互いの干渉を減らす。~~
- ~~ルビの親文字列（rbタグ）およびルビ文字列（rtタグ）についてline-heightをゼロにする。~~
- ~~現時点では、ルビ関連の要素に対して設定可能なプロパティは限定的であるため、displayプロパティを上書きする。rubyタグ部分をFlexコンテナとし、rbタグ部、rtタグ部をFlex子要素にして表示位置を再定義する。~~

それでそれなりの結果は出せるが、今回は

- ルビを含む行の高さを、通常の行と揃える。
- ルビの表示高さを調整。

# ルビを含む行の高さを下げる
```CSS:rubyタグのCSS
ruby{
  padding-top: 1em;
}
```
説明できないが、これでルビのある部分の行間が他と同じになる。

# ルビ文字列の位置を調整
```CSS:rtタグのCSS
rt{
  transform: translateY(.8em);
}
```
ルビが上の行に重なってしまったので、好みの位置まで下げる。

# Firefoxへの対応
　Firefoxでは rt要素が transformで動かせない（ display: block ではなく ruby-text で定義されてて色々特殊っぽい）のでルビ文字列を spanで括りそれを移動させる。ほかに今のところ思いつかない。
[SwiftUI] List の簡単なサンプル

<img width="1546" alt="スクリーンショット 2020-06-28 14.04.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45822/025f86f7-284e-96f1-a414-a7acecedcc69.png">

# Code

```swift:ContentView.swift
import SwiftUI

struct User: Identifiable {
    let name: String
    let bio: String
    let id = UUID()
}

let users = [
    User(name: "taro", bio: "I like sushi."),
    User(name: "yuki", bio: "I like music."),
    User(name: "mu", bio: "Software engineer")
]

struct ContentView: View {
    var body: some View {
        List(users) { user in
            VStack(alignment: .leading) {
                Text(user.name)
                Text(user.bio)
                    .font(.subheadline)
                    .foregroundColor(Color.gray)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```
【kubernetes】リソースの略称まとめ

# はじめに
kubectlコマンドを使用する時に、persistentvolumeclaimsなどをそのまま入力するのは面倒。
そこでkubectlには略称が存在する。

本記事では、リソースの略称をまとめる。

# リソースの略称

| NAME                   | SHORTNAMES |
|------------------------|------------|
| configmaps             | cm         |
| endpoints              | ep         |
| events                 | ev         |
| namespaces             | ns         |
| nodes                  | no         |
| persistentvolumeclaims | pvc        |
| persistentvolumes      | pv         |
| pods                   | po         |
| replicationcontrollers | rc         |
| serviceaccounts        | sa         |
| services               | svc        |
| controllerrevisions    | apps       |
| daemonsets             | ds         |
| deployments            | deploy     |
| replicasets            | rs         |
| statefulsets           | sts        |
| cronjobs               | cj         |
| jobs                   | batch      |
| events                 | ev         |
| daemonsets             | ds         |
| deployments            | deploy     |
| ingresses              | ing        |
| replicasets            | rs         |
| ingresses              | ing        |
| storageclasses         | sc         |

## 補足
```
$ kubectl api-resources
```
で確認できます。
AWS日記12 (Translate)

# はじめに
今回は Amazon Translateを利用して翻訳機能を試します。

[今回作成したAmazon Translate の翻訳機能を試すページ](https://labo.systems/translate)

# 準備
[Lambda , API Gatewayの準備をします。]
(https://qiita.com/tanaka_takurou/items/3f93295de6cff060ec09)

[Amazon Translateの資料]
[Amazon Translate](https://aws.amazon.com/jp/translate/)

# WEBページ・API作成
GO言語のAWS Lambda関数ハンドラー aws-lambda-go を使用してHTMLやJSONを返す処理を作成します。
また、Translate を使用するため aws-sdk-go を利用します。

[参考資料]
[AWS SDK for Go API Reference](https://docs.aws.amazon.com/sdk-for-go/api/service/translate/)
[aws translateコマンドをシェルのエイリアスに設定すると便利](https://qiita.com/minamijoyo/items/32833d981ff2f82e5fa1)
[Amazon Translateを使ってみた＆自動翻訳付きチャットを作ってみた](https://qiita.com/kojiisd/items/e90b877123b494a419fe)



##### 翻訳するには Text を使う。

```golang:main.go
func translateText(message string, sourceLanguageCode string, targetLanguageCode string)(string, error) {
        svc := translate.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })
        params := &translate.TextInput{
                Text: aws.String(message),
                SourceLanguageCode: aws.String(sourceLanguageCode),
                TargetLanguageCode: aws.String(targetLanguageCode),
        }
        res, err := svc.Text(params)
        if err != nil {
                log.Print(err)
                return "", err
        }
        return aws.StringValue(res.TranslatedText), nil
}
```


※ 入力された文字列が日本語か英語か判断するため、今回は簡易的にアルファベットを含むかどうかで判定しました。

```golang:main.go
func sendMessage(message string)(string, error) {
        if regexp.MustCompile(`[a-zA-Z]`).Match([]byte(message)) {
                return translateText(message, languageCodeEn, languageCodeJa)
        }
        return translateText(message, languageCodeJa, languageCodeEn)
}
```


# 終わりに
今回はAmazon Translateを試しました。
Mizukiのエンジニア的自己紹介その4 〜ちゃんとプログラミングやろう〜

WordPress弄りすぎてPHPがちょっとできるようになったMizuki。
でもやっぱりちゃんとイチからプログラミング勉強する経験も必要だと思ったんだ。
そんなPaizaやってみた記録！
#なんかやったことないやつやってみたい
PHPはWordPress弄るうちに目が慣れた。
でもちゃんとイチから勉強してない。
この中途半端感を払拭する自分なりの方法が、別の言語の習得だった。
そんな私はPaizaラーニングでRubyをチョイス。
#わかりやすい映像、面白い課題、書きやすい環境
Paizaラーニングやってみたらすごかった。
左上に学習映像、その下にレジュメ的なもの、
そして右半分はブラウザ上に展開された開発環境…！
ブラウザ開けば即書ける。すてきすぎる。
そして課題が面白い。ドラ○エ的な。
ゲームプログラミングって興味なかったけど、
勉強としてはいろいろな技が習得できてとても楽しかった。
#おかげさまで結構書けるようになりました
スキルチェックしてみよう。
最初は入力の多さに戸惑うけど、慣れたら大丈夫。
私の場合わかりやすいラーニングのおかげでBランクまでは普通にいけた。
Aランクからは…ちょっと工夫しないと実行速度遅くてタイムアウトするので注意だ！
でも大丈夫。アルゴリズムの講座も用意されている。助かる〜
#この辺でめっちゃスカウトきた
まって
めっちゃスカウトくるやん
とりあえずおしごとほしい私は手当たり次第カジュアル面談。
最初はなかなかうまくいかない。
でも数こなすうちに見えてくるものもある。
気長に頑張ろう。
#見えてきたもの（私の場合）
やっぱWeb系行きたいなって思いました！
（WordPress絡んでると尚良し！）
やっぱりずっと付き合ってきたものって語れることも多いし、
面接も楽しい。このへんでPHPめっちゃ復習した。
#現状の結論
Paiza楽しいよ！
実際の現場の人とお話ししたことを踏まえてまたラーニングすると得るものも多いし、
使いこなせばかなり捗ると思います！
このままおしごときまるといいな…！
（決まるまでにGit入門とかもやっとこう…）

自己紹介はこの辺にして、次回からは技術的な話をしたい（願望）
複数のFutureの全ての処理が終わるまで待つ

# はじめに
- バッチ処理などでScalaの複数のFutureが全て処理を終わったらステータスを更新したいケースなど結構あるので実装メモ。

# 実装
- `Await.ready` と `Future.sequence` を用いて簡単に書ける。

```scala
import scala.concurrent.duration.DurationInt
import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutor, Future}

object Main extends App {
  implicit val ec: ExecutionContextExecutor = ExecutionContext.global

  println("Start.")
  val f1 = Future { Thread.sleep(1000); 1 }
  val f2 = Future { Thread.sleep(2000); 1 }
  val f3 = Future { Thread.sleep(3000); 1 }

  Await.ready(Future.sequence(Seq(f1, f2, f3)), 10.seconds)
  println("Done.")
}

```

# 実行結果
- 3秒くらい待つと終了するので想定通りに動いている。

```
Start.
Done.
```

- Awaitの待ち時間を10秒->2秒に変更して実行してみるとタイムアウト例外が発生して想定通り。

```
Start.
Exception in thread "main" java.util.concurrent.TimeoutException: Future timed out after [2 seconds]
	at scala.concurrent.impl.Promise$DefaultPromise.tryAwait0(Promise.scala:212)
	at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)
	at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:104)
	at scala.concurrent.Await$.$anonfun$ready$1(package.scala:174)
	at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:62)
	at scala.concurrent.Await$.ready(package.scala:124)
	at Main$.delayedEndpoint$Main$1(Main.scala:17)
	at Main$delayedInit$body.apply(Main.scala:9)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at scala.Function0.apply$mcV$sp$(Function0.scala:39)
	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
	at scala.App.$anonfun$main$1(App.scala:73)
	at scala.App.$anonfun$main$1$adapted(App.scala:73)
	at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:553)
	at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:551)
	at scala.collection.AbstractIterable.foreach(Iterable.scala:920)
	at scala.App.main(App.scala:73)
	at scala.App.main$(App.scala:71)
	at Main$.main(Main.scala:9)
	at Main.main(Main.scala)
```

# 参考
- https://qiita.com/mtoyoshi/items/297f6acdfe610440c719
AWS,GCP,Azureの対応用語表とベストプラクティス（階層・ユーザー・定義された権限編）

# はじめに

AWS,GCP,Azureを使っているのですが対応している用語が分かりづらかったのでまとめました。
また弊社のように今は小規模な組織で厳密に権限管理をするほどではないけど、スケールする可能性があり将来的な負債にはしたくないという方向けの**低工数だけど効果がある最適なベストプラクティス**をまとめました。
1年前の自分に読ませてあげたいことが書いてあります。
# 階層

| 階層|  AWS |GCP  |    Azure   |
|:--------:|:--------:|:--------:|:--------:|
| ルート |         組織 |   組織  |   AzureAD ※2    |
|環境の<br>グループ ※1 |       OU |       フォルダ  |   管理グループ   |
| 独立した環境  |       アカウント |   プロジェクト     |    サブスクリプション   |
| VMなどの<br>グループ |       |            |    リソースグループ    |
| VMなど |        リソース |     リソース    |   リソース   |

※1:環境だけでなくグループ化したものもグループ化できる、ファイルとディレクトリをイメージすると分かりやすい
※2:厳密にはAzureADは認可認証サービスなので少し違う

### ベストプラクティス
AWSのアカウントなど「独立した環境」レイヤーで開発、本番環境を**分離**することをお勧めします。
独立している環境なのでヒューマンエラーが起きにくくなります。
また、組織が大きくなったときに「独立した環境」をそのまま「環境のグループ」に移動するのは比較的簡単ですが、「独立した環境」内を整理するのは大変です。

# ユーザー

| ユーザー　　|  AWS |GCP  |    Azure   |
|:--------:|:--------:|:--------:|:--------:|
| 個人 |ユーザー |   Google<br>アカウント ※3  |ユーザー   |
|グループ |    グループ | Google<br>グループ |グループ   |
|マシンユーザー ※1|ロール ※2 |サービス<br>アカウント   |サービス<br>プリンシパル|

※1:プログラムなど人以外がアクセスするときの認証情報を持った仮想のユーザー
※2:「プログラムによるアクセス」ユーザーという選択肢もある
※3:個人のGoogleアカウントではなくGsuiteもしくはCloudIdentityを用いた方が管理が楽です

### ベストプラクティス
組織がスケールする可能性があるならば、個人ではなく**グループ**で管理することをお勧めします。入退社や新規開発の度に管理するのは組織が大きくなるとどんどん大変になります。
マシンユーザーは**コード管理**をお勧めします。環境による差分を生じさせないためです。

# 「独立した環境」の定義された権限

| ユーザー|  AWS |GCP  |    Azure   |
|:--------:|:--------:|:--------:|:--------:|
| 全ての権限 |  Administrator<br>Access |   オーナー  |  所有者   |
|権限以外の権限 |    PowerUser<br>Access |    編集者 |   共同作成者   |
|   |    |  閲覧者 ※1   |       |
| 読み権限 |   ReadOnly<br>Access  |   参照者   |    閲覧者   |

※1：Firestoreのレコード書き換えることができてしまうので注意


### ベストプラクティス
各環境で必要な権限をグループに付与しましょう。
開発者グループには
開発環境では「全ての権限」もしくは「権限以外の権限」、
本番環境では「読み権限」と必要ならば特定のリソースのみの権限がお勧めです。
弊社では、開発者・ITインフラ・ITインフラ特権・アドミンにグループ分けをして各環境で**必要な最小権限**を与えております。


# 最後に
最後までご覧いただきありがとうございます。
**最小権限の原則**を満たしつつ権限不足で業務に支障が出ないようにすることは大変難しいですが、ITインフラ担当者の腕の見せ所だと思いますので私を含め皆さん頑張りましょう！
間違いなどございましたらコメントいただけますと幸いです。
【heroku,FuelPHP】デプロイ時のyahooメール設定方法

思うようにメール設定がうまくいかず時間がかかったので、同じ環境の方がさくっと対処できるように手順を残しておきます。

#対象の方
herokuにFuelPHPを使ったwebサービスをデプロイ済みでyahooメール設定がうまくいかない方。
※MacOS環境での方法を記載しています。

#手順
５ステップで解説していきます。

1.config.phpにemailを追加
2.email.phpを..fuel/app/configに複製
3.email.phpを編集
4.yahooメールの設定変更
5.email.phpのnewlineを編集（それでもエラーが出る場合）


##1.config.phpにemailを追加
fuel/app/config/config.phpのpackages=>array()にemailを追加
※Emailパッケージ読み込んでEmailクラスを利用できるようにします。

```fuel/app/config/config.php

'packages'  => array(　　 //
  'email',　　　　　       //新規で追加
),

```

##2.email.phpを..fuel/app/configに複製
/fuel/packages/email/config/email.phpをコピーし、/fuel/app/configディレクトリ内にemail.phpを複製します。
※mail設定の編集はこちらで行なっていきます。

##3.email.phpを編集

複製したemail.phpを下記のように編集していきましょう。

```fuel/app/config/email.php
...
 /**
  * Mail driver (mail, smtp, sendmail, noop)
  */
  'driver' => 'smtp',                       //smtpに変更
...

 'smtp' => array(
	'host'     => 'smtp.mail.yahoo.co.jp',　//変更
	'port'     => 587,　　　　　　　　　　　　　//変更
	'username' => 'yahooメールのログインID',　  //変更
	'password' => 'yahooメールのパスワード', 　　//変更
	'timeout'  => 5,
	'starttls' => false,
	'options'  => array(
	),
 ),
...

```

設定が気になる方は[yahoo公式サイト(メールソフトやモバイル端末での設定)](https://knowledge.support.yahoo-net.jp/PccMail/s/article/H000007321)にも解説してあるので参考にしてみてください。
<img width="665" alt="スクリーンショット 2020-06-28 12.58.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648324/f7adcb1f-ce3e-ff14-e8ad-0ffd071e4427.png">

##4.yahooメールの設定変更
ここまで設定して下記の認証エラーが出る場合はyahooメール側の設定を確認してみましょう。
<img width="840" alt="スクリーンショット 2020-06-28 13.01.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648324/72ea78c5-4fdb-5ab5-8b62-dccf4c7f298d.png">

先ほどと同じ[yahoo公式サイト（Yahoo!メールでの設定）](https://knowledge.support.yahoo-net.jp/PccMail/s/article/H000007321)に解説してあるので確認してみましょう。
※「Yahoo! JAPAN公式サービス以外からのアクセスも有効にする」にチェックを入れ、「IMAP」「POP」「SMTP」をそれぞれ「有効にする」を選択できていればOKです。

私はここに行き着くのに結構時間が掛かってしましました笑


##5.email.phpのnewlineを編集（それでもエラーが出る場合）
4まで設定してメール送信できた方は見なくて良いですが、私の場合は下記エラーが出ました。
<img width="833" alt="スクリーンショット 2020-06-28 13.06.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648324/6a08b4f1-85bc-1072-0564-84b81db2fca0.png">

色々と試してみましたが、fuel/app/config/email.phpのnewlineを変更することでメール送信できるようになりました。

```fuel/app/config/email.php
/**
 * Newline
 */
 'newline' => "\r\n",                //"\n"から変更

```

gmailの場合ですが、[公式アカウント](http://fuelphp.jp/docs/1.7/packages/email/troubleshooting.html)にも記載ありました。

改行のコードを変更する必要があるみたいですね。
<img width="590" alt="スクリーンショット 2020-06-28 13.27.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648324/e0164aae-55b8-d4ac-7c6d-05a9584886bc.png">



それでは最後まで読んで頂きありがとうございました。

参考になった方はLGTMをポチッと押していただけると励みになります。
カラーミーAPIを利用して商品一覧のjsonを取得する

「カラーミーAPI」を利用して、
カラーミーで作ったショップの全商品一覧および各商品の詳細を、
別サーバー（ここではheteml）にjsonとして保存した時のソースコードです。
以下のようなコードをhetemlのweb以下に「products.php」として置き、
cronで10分ごとに動かし、
同ディレクトリに「cache.json」として保存します。

```
#!/usr/local/php/7.3/bin/php
<?php
$request_options = array(
  'http' => array(
  'method' => 'GET',
  'header'=> "Authorization: Bearer オーソリゼーションコードだよ〜\r\n"
  )
);
//アクセストークンなどAPI取得に必要な情報だよ
$context = stream_context_create($request_options);
//商品一覧を取得する
//先に商品が全部でいくつあるか取得する
$url = 'https://api.shop-pro.jp/v1/products.json'; //あとでoffsetで51件目以降の処理を作る
$response_body = file_get_contents($url, false, $context);//API取得に必要な情報を一緒に送る
$response_body = json_decode($response_body, true);
$all_the_products_num = $response_body["meta"]["total"];
//次に、1-50件、51-100件、と回していく
for($i = 0; $i < $all_the_products_num; $i++){
  $key_num = $i%50;
  if($i%50 == 1){
    $url = 'https://api.shop-pro.jp/v1/products.json?limit=50&offset='.($i-1);
    $response_body = file_get_contents($url, false, $context);
    $response_body = json_decode($response_body, true);
  }
  $product_ids[$i] = $response_body["products"][$i%50]["id"];
}
//productIDの一覧ができたので、それをもとに商品詳細のapiを叩く
$tmp .= "{\"product\":[";
for($i = 0; $i < count($product_ids); $i++){
    $url = 'https://api.shop-pro.jp/v1/products/'.$product_ids[$i].'.json';
    $response_body = file_get_contents($url, false, $context);//API取得に必要な情報を一緒に送る
    $result = json_decode($response_body);
    $tmp .= json_encode($result->{"product"});
    if($i != count($product_ids)-1){
      $tmp .= ",";
    }
}
$tmp .= "]}";
$file = '書き出し先のhetemlの絶対パス/cache.json';
// ファイルをオープンして既存のコンテンツを取得します
$current = file_get_contents($file);
// 結果をファイルに書き出します
file_put_contents($file, $tmp);
?>
```
MacでVScodeのplantUMLがうまく動かないやつの対処

# 出てるエラー
僕はユースケース図でactorを書こうとしている時に出ました。

とりあえず画像のようにtestdotと打ち込めば、自分の書き方が悪いのかライブラリがないのかをチェックできます。

<img width="500" alt="スクリーンショット 2020-06-28 13.10.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199256/9af45279-0f19-9ef4-a47c-443b271262de.png">


# 解決策
こちらを参照
https://plantuml.com/ja/graphviz-dot


1. `brew install libtool`を実施。やたら時間かかった。。
2. `brew install graphviz`を実施。

ここまでいくと先ほどの`testdot`が通るようになる

<img width="839" alt="スクリーンショット 2020-06-28 13.31.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199256/86c87f65-84a7-5be2-4727-a638ff0cbdef.png">

# 無事使えるようになりました！
<img width="846" alt="スクリーンショット 2020-06-28 13.33.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199256/8a58ca9b-5cac-e12d-ee0a-816be4a9d5e2.png">
Goで競プロメモ | 約数カウント

最近、競技プログラミングを始めたのですが、才能はなく、要領も悪く、解法を覚えるのも苦手でどうしようもない弱者なのだと思い知る日々です。それでも、強くなりたいので、よく出てきそうなアルゴリズムやデータ構造や細かい Tips など何でも、メモできることはして、少しずつ知識と経験を蓄えていきたいと思って書いています。

今回は「約数カウント」についてメモします。

# 「約数カウント」

## 何をやるか

$1$ からある正の整数 $n$ までの整数のそれぞれについて、正の約数の個数を数え上げる。

## どうやるか

1. 長さ $n + 1$ の整数配列 $A$ を用意する。（つまり $n$ までのインデックスを持つ配列）
2. $1$ から $n$ までの整数について、配列 $A$ 内でその整数の倍数をインデックスとする要素をインクリメントしていく。

> - 計算量: $O(n \log n)$
>   - [調和級数](https://qiita.com/ageprocpp/items/f6661deaa09dda124132)になるため。（[@ganariya](https://qiita.com/ganariya) さんありがとうございます！）

## コード

```go
divisorCounts := make([]int, n+1, n+1)
// 1 から n までの i について
for i := 1; i <= n; i++ {
	// i の倍数を処理
	for j := i; j <= n; j += i {
		divisorCounts[j]++
	}
}
```

# 「約数カウント」を使う問題

## [AtCoder ABC172 D Sum of Divisors](https://atcoder.jp/contests/abc172/tasks/abc172_d)

> 私の解答はこちら: https://atcoder.jp/contests/abc172/submissions/14795780

上の説明で示した通りのコードを使います。

```go
func Solve(n int) int {
	divisorCounts := make([]int, n+1, n+1)
	// 1 から n までの整数 i について
	for i := 1; i <= n; i++ {
		// i の倍数を処理
		for j := i; j <= n; j += i {
			divisorCounts[j]++
		}
	}

	ans := 0
	for i, v := range divisorCounts {
		ans += i * v
	}
	return ans
}
```

## [AtCoder ABC134 D Preparing Boxes](https://atcoder.jp/contests/abc134/tasks/abc134_d)

> 私の解答はこちら: https://atcoder.jp/contests/abc134/submissions/14843714

この問題では、「約数カウント」を少し変形した形で使います。

「約数カウント」では **$n$ の約数は $n$ 以下の範囲にしか存在しない** ことを利用して、小さい $i$ から順番にその倍数を加算していくことで効率的に約数の個数を数え上げていきました。配列において **インデックスの小さい要素から値を確定させていく** イメージです。

それに対して以下では、これを逆転して **$n$ の倍数は $n$ 以上の範囲にしか存在しない** ことを利用します。配列において **インデックスの大きな要素から値を確定させていく** イメージです。

したがって、「約数カウント」とは対照的に、**配列の後方** から要素を処理します。

```go
func Solve(a []int) []int {
	inOrNotList := make([]int, len(a)+1, len(a)+1)
	var ans []int
	// n から 1 までの整数 i について
	for i := len(a); i >= 1; i-- {
		sum := a[i-1]
		// i の倍数を処理
		for j := i * 2; j <= len(a); j += i {
			sum += inOrNotList[j]
		}
		if sum%2 == 1 {
			inOrNotList[i] = 1
			ans = append(ans, i)
		}
	}
	return ans
}
```

## [AtCoder ABC170 D Not Divisible](https://atcoder.jp/contests/abc170/tasks/abc170_d)

> 私の解答はこちら: https://atcoder.jp/contests/abc170/submissions/14849721

この問題は、 **配列において他の要素のどれでも割り切れない要素を数える** というものです。

これは言い換えれば、 **配列において他の要素の倍数になっていない要素を数える** ということですから、これは配列の各要素について、そのすべての倍数に対して（その数の約数が配列に含まれること示す）印をつけていくことで確かめられます。

```go
func Solve(A []int) int {
	sort.Sort(sort.IntSlice(A))
	max := A[len(A)-1]
	divisible := make([]int, max+1, max+1)
	// 配列内の要素それぞれについて
	for _, n := range A {
		if divisible[n] != 0 {
			divisible[n]++
			continue
		}
		// 要素の倍数を処理
		for multiple := n; multiple <= max; multiple += n {
			divisible[multiple]++
		}
	}
	notDivisibleCount := 0
	for _, n := range A {
		if divisible[n] == 1 {
			notDivisibleCount++
		}
	}
	return notDivisibleCount
}
```

# 最後に

私は記事を書くのも初心者ですから、分かりにくいところや説明不足なところがあったらどんどん厳しく教えていただけると幸いです。

また、自分で過去問に取り組む中で同系統の問題に遭遇したら、随時ここへ追加していきたいと思いますが、知っている方はコメントで教えていただけるととても嬉しいです。

最後まで読んで下さってありがとうございました。
Mizukiのエンジニア的自己紹介その3　〜WordPressはいいぞ〜

WordPressとの絡み、東京編です。
いってみよー！
#なぜか上京！それも芸能！
スカウトされちゃったんです…
元ミナミのオカマでありながら元バンドマン。
音楽スキルを買われての上京。
しかし大阪でWordPressを弄りすぎた私はつい言ってしまった。
「事務所サイト、もっとよく出来ますよ！」
#言っちゃったからにはやるしかない
今回の元の環境は素人でも簡単にWebサイトをカッコよく作れちゃうようなアレ。
編集の効率が悪い。私の知ってるシステムならもっと楽なはずだ。
無性にやりたくなった。なんでだろうね。
（※その結果はPaizaで企業様向けにリンク貼ってます。）
#カスタム投稿、カスタムフィールド…
流石にイチからテーマを作ることはしなかったものの、
今回はちょっと仕様がややこしい。
ただ最新情報を流せばいいってもんじゃない。
事務所の情報やお問い合わせフォームを固定ページに、
最新情報を投稿に、

じゃあ所属タレントはどこに書こう…？

そこでカスタム投稿というシステムを知った。
なんならプロフィールデータとか内容入れるだけで整形して欲しい。
ACF…！そういうのもあるのか…！
（現在の事務所サイトは諸事情によりACFは使っておりませんが、仕様変更前に使ってました。）
身長、スリーサイズ、出身地…
カスタム投稿タイプとそれに対応するカスタムフィールドを作り、
子テーマに表示するコードを書く。
めっちゃ編集しやすくなった…しかも体裁が整う…
すてき…！

#苦労した点
親テーマがオシャレすぎてキレイにカスタム投稿を表示するのが大変だった。
黒背景に斜めに切られた投稿表示。クセがすごい。
おかげでめっちゃフロントエンドの勉強になった。
カスタム投稿ループはググれば出てくるけど、
あの形にするにはコード読んでうまくハメるしかないもの。
（※その結果はPaizaで企業様向けにリンク貼ってます。）

#そしてこれを本業にしようと決意した
きっかけはコロナ。
なかなか活動も生活もままならず、
とりあえずこの先生きのこるにはと考えた結果、
このWordPressで培ったスキルを活かすべきだと思い…

次回、Mizuki、Paizaに登録する！
〜つづく〜
Pycharm への pypy 導入手順【競プロ】

# はじめに
趣味の競技プログラミング用に IDE として Pycharm を愛用しています。
特にコード補完、ライブテンプレート、Vim エミュレーターが気に入っています。

今回は、ローカル環境でのコードテスト実行のために pypy を導入するにあたり、
やや手間取ったので手順を共有します。

# 実行環境
　OS：Windows 10 Pro (64 bit)
　Pycharm：2020.1 (Community edition)

# 手順 1： pypy インストールモジュールの入手
公式サイトから各環境におけるインストールモジュールを入手します。

　https://www.pypy.org/download.html

本環境では以下を用いました。

　Python 3.6 compatible PyPy3.6 v7.3.1 - Windows binary (32bit)  

64bit OS ですが、現在のところ問題なく使用できています。

# 手順 2： Pycharm インタープリター設定
Pycharm を起動し、メニューバー > File > Setting から設定パネルを開きます。

Python Interpreter を選択後、画面右上の設定ボタン（歯車のようなアイコン）をクリックします。
![stng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443861/7b566fb7-e9d2-30eb-a2a1-53e6e28ece9e.png)

Add Python Interpreter パネル上で System Interpreter を選択後、右上の三点リーダーアイコンをクリックし、先のインストールモジュールを展開したフォルダ内 pypy3.exe を選択します。
![interprt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443861/802f00ee-b75d-41dc-8dee-0af5d7f7c1c7.png)

スケルトンファイルが自動作成され、pypy 環境が使用可能になります。

導入設定は以上です。

# 手順 3： インタープリターの変更
画面右下のステータスバーから変更すると便利です。
![切り替え.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443861/de55df68-0390-d950-ca98-aa54b8784815.png)


# 実行例
　ABC 172 C Tsundoku, Case: b08.txt
　https://atcoder.jp/contests/abc172/tasks/abc172_c
　提出：https://atcoder.jp/contests/abc172/submissions/14791414

Python 3.8.2: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443861/e1f64c6b-86c7-e2e0-c03b-8553e943dbcf.png)

Pypy3 7.3.1: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443861/ec9ff0da-3fda-9229-ab57-b4d15b64c595.png)

時間計測は以下を参考にしました。（sec → ms に変更しています。）

　Pythonで処理の時間を計測する冴えた方法：
　https://qiita.com/hisatoshi/items/7354c76a4412dffc4fd7

# おわりに
筆者は計算量の見積もりすこぶる甘く、コンテスト中に Python で TLE したコードを見ながら、

「pypy に変えて出せばワンチャンあるか...?」

という悪い心に支配されることが、しばしばあります。
しかし実際はワンチャンありません。そもそもの実装が悪いのです。

手元でサッと試して諦めるために Pycharm への pypy 導入を試みましたが、
言及した日本語ドキュメントが見当たらなかったため投稿しました。

本稿が、どなたかのお役に立てば幸いです。

# 参考
1. Jetbrains 公式：https://www.jetbrains.com/help/pycharm/configuring-python-interpreter.html#add-existing-interpreter
2. https://stackoverflow.com/questions/31456583/how-can-i-use-pypy-as-standard-default-interpreter-in-pycharm-4-5-2
Processing 3.5.3 (電子アート/ビジュアルデザイン用プログラミング言語) Raspberry Pi 4で動く?動かない?

[Processing 3.5.3](https://processing.org/) が Raspberry Pi 4で動く動かないの話です。
2020年6月28日現在、私個人の動作確認により少し切り分けられ、動かない動作環境があることがわかりました。

## 動作した環境
- Raspberry Pi 4 (4GB) + Raspberry Pi OS (32-bit) + LXDE + openjdk-11 + Processing 3.5.3 (+ xrdp from Windows 10)

```
$ hostnamectl
$ Operating System: Raspbian GNU/Linux 10 (buster)
$ Kernel: Linux 4.19.118-v7l+
$ Architecture: arm
```

さて、LXDEまで入れたら、

```
$ sudo update
$ sudo apt install default-jdk
$ curl https://processing.org/download/install-arm.sh | sudo sh
```

完了、再起動し、デスクトップメニューからProcessing(プログラミングかグラフィックスに入っている)を選ぶと瞬時にスプラッシュが出ます。スプラッシュからIDEまでは少し待ちます。

##動作していない環境
- Raspberry Pi 4 (8GB) + Raspberry Pi OS **beta (64-bit)** + LXDE + openjdk-11 + Processing 3.5.3 (+ xrdp from Windows 10)

```
$ hostnamectl
$ Operating System: Debian GNU/Linux 10 (buster)
$ Kernel: Linux 5.4.42-v8+
$ Architecture: arm64
```

さて、こちらもLXDEまで入れたら、

```
$ sudo update
$ sudo apt install default-jdk
$ curl https://processing.org/download/install-arm.sh | sudo sh
```

導入スクリプト処理は完了します。再起動もします、デスクトップメニューからProcessingを選びますが、マウスカーソルがしばらく砂時計になってやがて静かに元通り。

さらに、ダメ元で、[Tar-balls](https://pi.processing.org/download/)から入れて動作確認してみました。

```
dk4130523@raspberrypi:~/processing-3.5.3 $ processing
dk4130523@raspberrypi:~/processing-3.5.3 $ Exception in thread "AWT-EventQueue-0" java.awt.HeadlessException`
```

default-jre-headless (2:1.11-71) は入っているのですが、だめでした。もう少し調査してみます。

## 参考: xrdpから接続して動作している画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159724/bd706a65-5a94-98a3-2c13-705318d4160e.png)

## まとめ
2020年6月28日現在、Raspberry Pi 4 running Raspberry Pi OS **beta (64-bit)** 環境では、すばらしい Processing 3.5.3 が動作しない(落ちる)というご報告でした。betaが外れるころには動くのではないかと思います。

## 追記: xrdp 環境導入
```
$ sudo apt install xrdp xserver-xorg xinit raspberrypi-ui-mods
$ sudo service xrdp restart

# 好みで、
$ sudo apt install rc-gui fcitx-mozc
```
以上です。
Mizukiのエンジニア的自己紹介その2　〜WordPress、もっと思い通りにしたい〜

前回所属する会社のWebサイトを総入れ替えしてしまったMizuki。
そこからさらに深みにハマるきっかけとなったサイトの制作秘話など。
#「いつやるの？今でしょ！」
私がある時新たに任された業務。
それは映像授業の制作だった。
ひたすらカメラの前で喋り続ける日々。
機材が過熱するたび冷蔵庫で冷やす（マネしてはいけません）。
そして完成させた時私は思った。
「配信サイト見づらくね？」
#デフォルトテーマも使いようなのでは
左サイドにメニュー、デカいアイキャッチ画像エリアに押しやすそうな記事送りボタン。
これ映像配信にうまく使えるのではないか…
ここに表示したいものをハメるにはどうすれば…
そして私はついにテーマ編集に手を出してしまった！
#自分で書いて動く快感
表示したいものを表示したいところに書いてみる。
出来合いのオシャレな見た目と実現したい機能の融合。
面白い…面白いぞ…！
そして例によって休暇中に本番環境へ。
これまたウケる。
たのしい…！

大阪でWordPressと出会った話はこのへんまで。
次回からはちょっと時期が飛んでなぜか上京しちゃいます。

〜つづく〜
railsでFailed to open TCP connection to oauth2.googleapis.com:443 (getaddrinfo: Name or service not known)　というエラーがでた。

<h1>Failed to open TCP connection to oauth2.googleapis.com:443 (getaddrinfo: Name or service not known)というエラーがでた。
</h1>

環境 VirtualBox vagrant (CentOS)


<p>RailsでOminiauth使って、Googleログイン機能作って、Googleログインしようとした。すると</p>
Failed to open TCP connection to oauth2.googleapis.com:443 (getaddrinfo: Name or service not known)

というエラーが。

<h3>解決策</h3>

vagrant reloadをすることで治った。
どうやら、途中で、PCをスリープにすると、CentOSのネットワークに障害が起きてしまうようだった。
その場合はvagrant reloadしなくてはならない。
raspberry pi 4でopencv-pythonを頑張って動かすメモ

# python3.8では現状無理ぽ

そもそも`pip install opencv-python`が失敗するので諦めましょう。

## python3.7だと動くぞ！！

### 前提パッケージ

```
sudo apt install libjpeg-dev libtiff5-dev libjasper-dev libpng-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libatlas-base-dev gfortran libhdf5-dev libhdf5-serial-dev libhdf5-103 libqtgui4 libqtwebkit4 libqt4-test python3-pyqt5 python3-dev
```

#### 注意!!

[opencv-python リリースバージョン一覧](https://www.piwheels.org/simple/opencv-python/)

現状の最新版である`opencv-python==4.1.1.26`はなんだか知らないけど動きません。一つ前のバージョンを指定してインストールしましょう。やれやれだぜ

```bash
pip install opencv-python==4.1.0.25
```
最後に確認。

```python
Python 3.7.7 (default, Jun 28 2020, 12:02:37) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'4.1.0'
>>> 
```

## 引用・出典・参考にさせて頂いた記事

- [ラズパイでpython3にopencvを入れたらエラーが出た【対処法】](https://qiita.com/XM03/items/48463fd910470b226f22)
- [Raspberry Pi 4 に OpenCV を楽に入れる](https://qiita.com/naoppy/items/8a2178383859178e6d7e)
Mizukiのエンジニア的自己紹介その1　〜WordPressとの出会い〜

そろそろいい加減Webを仕事にしようとしているMizukiです。
今回はそのきっかけであるWordPressとの出会いについてお話しします。
#はじめての昼職
当時まだ男子でありながら黒髪ロングぱっつんだったMizuki、
当初は順当にミナミの女装バーで働き始めた…
が、そこで出会ったシャッチョさんに誘われフリースクール的なところで数学・英語を教えることに。
この頃はまだ機械に強いだけのフレンズだった…
#古くなったWebサイト
その会社はWebサイトを外注していた。
しかしそれから年月が経ち、スマホ時代にもかかわらず非レスポンシブで見辛い。
ある時からそのサイトの更新業務を任されるようになった。
ここで機械に強めな私は思った。
「これ自分でなんとかできないのか…？」
#その名はWordPress
更新がてらメニューにある項目を見てしまう私。
どうやらテーマやプラグインを自分で変更できるらしい。
「おもろそうやん…」
とりあえず許可を得て出来合いのレスポンシブテーマを適用してみた。
それが結構ウケた。
これに味をしめた私は、WordPressの世界へまんまとハマってしまう…
#とりあえず作ってみよう！
この当時はまだ子テーマをゴリゴリいじるなんてことはしていなかった。
テーマもプラグインも数え切れないほどある。
組み合わせればいいサイトができそうだ。
そう思った私は会社に提案し…
#初心者がいきなりマルチサイト
その会社はたくさんの校舎を持っていた。
各校舎でブログを書きたい。でもトップページに更新を反映したい。
そんな素敵なシステムにすべく、Google先生や湊町のジュンク堂で調べまくった。
そして年末に完成、冬休み中に本番環境へ。
まだ大したことはしていないが、なんせ規模がデカい。
達成感が半端じゃなかった。

このあたりから出来合いのプラグインやテーマに満足できなくなり…？

〜つづく〜
renpyでルビを振るまで

renpyはhtmlのようにたくさんのタグがありますが、ルビを扱うには多少の設定が必要です。

そのままhtmlのように<code>rb</code>タグを使うと下の画像の様に重なって表示されます。

```python

e "\"{rb}事故{/rb}{rt}ジコ{/rt}\"る奴{rt}ヤツ{/rt}は…\"{rb}不運{/rb}{rt}ハードラック{/rt}\"と踊{rt}ダンス{/rt}\"っちまったんだよ…"

```
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230043/4a9f3fc1-af15-e28e-68b9-7c467106859e.jpeg)

そうならないためにはどこかに以下のスニペットを入れます。

```python

style ruby_style is default:
    size 12
    yoffset -20

style say_dialogue:
    line_leading 12
    ruby_style style.ruby_style

```
これで上手く表示されるようになりました。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230043/c4fcb695-b732-c80d-b390-37d5ef2d9e0f.jpeg)


style周りは基本gui.rpyに入れますが、サンプルではscript.rpyに直接入れています。

リポジトリを置きましたのでつまずいたときにはご覧ください。
https://github.com/misogihagi/renpy_ruby

ただこのやり方では文字の大きさを静的に設定するしかないのでどうにか動的に指定する方法があればコメント等でお願いします:wave:。