OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScriptで+++は許されない+ ++は許される

#+++,---とは
これらは一つの演算子ではなく、それぞれ+と++または++と+の組み合わせ、それの-番です。
わかりやすくいえば一つずつ増やして足していくということですね。

```javascript
var a=0;
var b=13;
console.log(a+ ++b) // 14
a--;
console.log(a++ +b) // 13
```

~~これがスペースを開けずに+++にするとエラーが出ます。もちろん理由は解析できないからです。
ちなみに++-や--+は使えます。~~

なんか書いてたらごっちゃになってました。私が書きたかったことはこちらになります。

```javascript
var b=13;
console.log(1+++b) // Uncaught SyntaxError: Invalid left-hand side expression in postfix operation
console.log(b+++1) // 14
console.log(1+ ++b) // 15
console.log(++b+1) // 15
```
つまり、+++は++と+という解釈になるということですね。なのでインクリメントをする際はスペースを開けるか変数を左に持っていく必要があります。
個人アプリ作成＃３

## 投稿画面の作成
<img width="1428" alt="スクリーンショット 2020-07-13 20.01.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663122/c6a5bb0a-a10e-fc56-13c4-1798d14541cd.png">

## application.html.haml
= yield の上にヘッダー下にフッターを記述する事によりどのページに行ってもヘッダーとフッターがある状態になる
<img width="707" alt="スクリーンショット 2020-07-13 20.04.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663122/2850573e-98c0-24fd-51c7-ba8309b710b0.png">
[scss]行を一行で表示して、末尾を「...」とする方法。二行もあるよ。


# これはなに
備忘録です。個人アプリで使ったので、すぐに引き出せるよう残しときます。

# さっそくコード

一行で表示させて、末尾を「...」とするやり方

```
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
```

二行で表示させて、末尾を「...」とするやり方

```
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
```

以上です！ありがとうございました！
AWS SDK のSSL証明書エラーが出た場合【Windows10】

* よくある、実行環境にSSL証明書がない場合に発生するエラー  

```
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) in xxx
```
```
cURL error 77: error setting certificate verify locations:
  CAfile: xxx
  CApath: none (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) in 
xxx on line 195
```
* 解決策  
cURLサイトから証明書をダウンロード出来るらしい  
https://curl.haxx.se/docs/caextract.html  
サイト内の **cacert.pem** というリンクからダウンロード出来る   
ダウンロードしたら適当な場所に配置して、php.iniの設定  

```
openssl.cafile='C:\tools\php\extras\ssl\cacert.pem'
```
apacheとかnginxならサービスを再起動
これで完了

参考： https://docs.aws.amazon.com/ja_jp/sdk-for-php/v3/developer-guide/faq.html
Rails×Herokuでcreateやupdateが急にできなくなったとき

基本的には[この記事](http://kayakuguri.github.io/blog/2016/07/19/postgresql-seqence/)の通りにやっただけなのだが、自分用にもメモ。

`heroku logs --tail`してみると

> duplicate key value violates unique constraint "posts_pkey"

（今回は`posts`テーブルの値をupdateしようとしておきたので、`posts_pkey`の部分は各自のテーブル名によって変わる。）

Postテーブルの一番大きなidが154だったので、Posticoの「SQL Query」で以下を打って解消。

```sql

SELECT last_value FROM posts_id_seq /* 最大のidを確認するクエリー */
SELECT setval('posts_id_seq', 155);
```

ただし本来は数字は154を指定すればOKなはずだが、なぜかうまくいかなかったので1つ飛ばす形となった。

## 原因

今回はStaging環境でおきたことで、localhost:3000やproduction環境では起きなかった。原因はやはりStaging環境のDBとproduction環境のDBを揃えようとして、Postico上でExportしたCSVファイルをImportするときに、こんかいのシーケンス番号というのがおかしくなってしまったようだ。

PosticoではImport時に既存のレコードを上書きすることができないため、一度テープルのレコードを全部消してインポートとかしていたがこれがまずかったよう…。
初心者によるプログラミング学習ログ 369日目

#100日チャレンジの369日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
369日目は、
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>昨日の作業・やったこと⇩<br><br>●筋トレ　5分　kindle読書10分<br>●ブログ記事1記事作成<br>●プログラミング学習369日目 4h<br>・メンターの課題<br><br>用足しとお昼寝3時間ぐらいしたのであんまりできなかったわ<a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアとつながりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a><a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a></p>&mdash; ぱぺまぺ@社畜✕投資✕ブロガー (@ppmp65) <a href="https://twitter.com/ppmp65/status/1282407684688371712?ref_src=twsrc%5Etfw">July 12, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Golangでプログレスバーを表示するためのパッケージ3選

Golangで処理を書いている時、特に時間がかかる処理の場合、進捗がどのくらい進んでいるのかを知りたい時がありますよね。そんな時使うのがプログレスバーだったりするわけですが、いい感じで利用できるパッケージがないか探してみると思いの外見つかったので3つリストアップしてみました！

リストアップするだけだと味気ないのでfor文を回す処理を利用してそれぞれ出力してみました。

マルチプログレスバーについての記事も書いているので興味のある方はこちらも是非！
[Golangでマルチプログレスバーを表示したい！！](https://qiita.com/Akazawa_Naoki/items/129e6733b4f85f2c643a)

# pb
[＞＞リポジトリ](https://github.com/cheggaaa/pb)

[＞＞ドキュメント](https://pkg.go.dev/github.com/cheggaaa/pb?tab=doc)

今回紹介する3つの中でスター数が2.7kと一番多い人気のパッケージです。人気なだけあって柔軟性が高そうな印象を受けました。

以下のコマンドでインストールできます。

```terminal:terminal
go get github.com/cheggaaa/pb/v3
```

pbをインストールして以下のサンプルを実行してみました。

```golang:main.go
package main

import (
	"time"
	"github.com/cheggaaa/pb/v3"
)

func main() {
	count := 100

	bar := pb.Simple.Start(count)
	bar.SetMaxWidth(80)

	for i := 0; i < count; i++ {
		bar.Increment()
		time.Sleep(time.Millisecond * 30)
	}
	bar.Finish()
}
```

動かした結果がこれ。

![pb.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454589/1d2494e4-a1f3-8c3f-6d03-cf35f2e4d5ec.gif)

# uiprogress
[＞＞リポジトリ](https://github.com/gosuri/uiprogress)

[＞＞ドキュメント](https://pkg.go.dev/github.com/gosuri/uiprogress?tab=doc)

同時に複数の進行状況バーをレンダリングでき、また、新しく処理が追加された場合でも追加の進行状況バーを追加できるようです。

以下のコマンドでインストールできます。

```terminal:terminal
go get -v github.com/gosuri/uiprogress
```

uiprogressをインストールして以下のサンプルを使って実行してみました。

```golang:main.go
package main

import (
	"time"
	"github.com/gosuri/uiprogress"
)

func main() {
	count := 100
	uiprogress.Start()
	bar := uiprogress.AddBar(count)

	bar.AppendCompleted()
	bar.PrependElapsed()

	for bar.Incr() {
		time.Sleep(time.Millisecond * 20)
	}
}
```

実行結果がこれ。

![uiprogress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454589/d7e57c20-cffb-959e-3c98-f3c1c3f1e03c.gif)

# progressbar
[＞＞リポジトリ](https://github.com/schollz/progressbar)

[＞＞ドキュメント](https://pkg.go.dev/github.com/schollz/progressbar/v3?tab=doc)

OSに依存せず利用できる、非常にシンプルなスレッドセーフなプログレスバーと言う謳い文句で案内されています。

以下のコマンドでインストールできます。

```terminal:terminal
go get -u github.com/schollz/progressbar
```

progressbarをインストールして以下のサンプルを使って実行してみました。

```golang:main.go
package main

import (
	"time"
	"github.com/schollz/progressbar"
)

func main() {
	count := 100
	count64 := int64(count)
	bar := progressbar.Default(count64)
	for i := 0; i < count; i++ {
		bar.Add(1)
		time.Sleep(40 * time.Millisecond)
	}
}
```

実行するとこんな感じ

![progressbar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454589/2508bb6d-b0b0-5891-b3be-298da3af44a8.gif)

# まとめ

個人的に、使い心地と見た目でpbが好みでした。

これ採用して早速実装してみます！
シンタックスハイライトって？

#シンタックスハイライトってなに？
Qiita完全初心者だから全くわからないけど、たぶん下のクールなコード表示方法のことかな？

```ruby:qiita.rb
Hello!World
```
記事メニューの？マークにコードが丁寧に示されている

```ruby:qiita.rb
```ruby:qiita.rb
puts 'code with syntax'
```

こりゃすごい。メモ代わりにします。
composer update でメモリオーバーする場合の対策

`composer update` や `composer require` した時に使用可能なメモリを超えるとこのようなエラーが発生します。

```shell-session
$ composer update
[13-Jul-2020 10:10:03 UTC] PHP Fatal error:  Allowed memory size of 2097152 bytes exhausted (tried to allocate 1974272 bytes) in Unknown on line 0
```

## 対策1. メモリ制限を外す

```shell-session
$ COMPOSER_MEMORY_LIMIT=-1 $(which composer) update
```

`COMPOSER_MEMORY_LIMIT=-1` 一時的に`php.ini`で設定されている`MEMORY_LIMIT`を無制限にしています。
`php` コマンドで実行するため、実行したいファイル名を絶対パス、または相対パスで指定する必要があります。
`$(which composer)` でComposerまでの絶対パスを指定してます。

- https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors

## 対策2. スワップファイルを作る

対策1でも解決しない場合、物理的にメモリが足りない可能性があります。(AWSのマイクロインスタンス等)
Swapファイルの作り方は下記のように作成します。

[スワップとは](http://e-words.jp/w/%E3%82%B9%E3%83%AF%E3%83%83%E3%83%97.html)

```shell-session
$ sudo /bin/dd if=/dev/zero of=/var/swap bs=1M count=1024
$ sudo /sbin/mkswap /var/swap
$ sudo /sbin/swapon /var/swap
```

1GB分のSwapファイルを作成しています。

```shell-session
$ COMPOSER_MEMORY_LIMIT=-1 $(which composer) update
```

Swapファイルは作成したままでも構いませんが、今度はディスク容量を1GB分使用してしまいます。
Swapファイルを削除する場合は下記のコマンドを実行します。

```
$ sudo swapoff /var/swap
$ sudo rm /var/swap
```

## 参考

- [コマンドラインオプション](https://www.php.net/manual/ja/features.commandline.options.php)
- [サービスを止めずにSWAP領域を拡張する。](https://qiita.com/sand_bash/items/30cb42ed53946e6eefa5)
- [dd コマンド](https://kazmax.zpp.jp/cmd/d/dd.1.html)
- [mkswap コマンド](https://kazmax.zpp.jp/cmd/m/mkswap.8.html)
- [swapon コマンド](https://kazmax.zpp.jp/cmd/s/swapon.8.html)
- [swapoff コマンド](https://kazmax.zpp.jp/cmd/s/swapoff.2.html)
- [AWS EC2, Cloud9 composer create-project でメモリ足りない問題の対策](https://qiita.com/ucan-lab/items/31831944586deed4b6c5)
- https://twitter.com/fagai/status/1298176547199660033?s=20
VSコードのターミナルでVisual Studioの開発者用コマンドプロンプトを使う

## やりたいこと
ここで、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/0585b0c8-75d5-802e-4040-bba97d4e80fa.png)
これを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/63b38a42-50cc-fc2f-5cd7-8dd49737f98c.png)

## やり方
以下のコマンドをターミナルで実行する。
> %comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat"

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/8eaad4ad-dbab-5521-b344-4b1158bf1ef2.png)
※Visual Studio 2017の開発者用コマンドプロンプトの場合

## 背景
- Power Apps Component Frameworkにてコンポーネントを作成するために、Power Apps CLIを使いたい
- そのためには、Visual Studioの開発者用コマンドプロンプトを使用する
- VSコードでコーディングは行うため、VSコードのターミナルにて、Visual Studioの開発者用コマンドプロンプトを開きたい

https://docs.microsoft.com/ja-jp/powerapps/developer/component-framework/implementing-controls-using-typescript

## コマンドはどこにあったか
- ショートカットの場所を開いた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/cf95458c-404d-adc2-fcbc-6359a8f26a2c.png)

- ショートカットのプロパティを開いたら、リンク先がbatファイルだった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/b97f163d-a551-1983-222d-30b5ed015c4c.png)

## 備考
- もっといいやり方があるそうだけど、これが一番わかりやすくて簡単そうだった
【Jest】Unit Test, Integration Test の違いを整理する  

[React Testing For Beginners Preview](https://www.youtube.com/playlist?list=PLLnpHn493BHEqP3gD1pCJYhxX6v2gBZzj) をみた後、
[Unit Test vs Integration Test: What's the Difference?](https://www.guru99.com/unit-test-vs-integration-test.html) を読んで得た知見をまとめています。

今回は、下記の``add``関数と``total``関数に対するテストコードを書いていきます。

```js:App.js
export const add = (x, y) => x + y

export const total = (shipping, subtotal) => {
    return '$' + add(shipping, subtotal)
}
```

# Unit Test

>The idea behind Unit Testing is to test each part of the program and show that the individual parts are correct.

個々の部分が正しいことを示すということですから、ここでは``add``関数に対するテストのことを指しています。

```js:App.test.js
import { add } from './App'

test('add', () => {
    expect(add(1, 2)).toBe(3)
    expect(add(3, 6)).toBe(9)
    expect(add(3, 6)).toBe(10)
})
```

結果はこうなります。
<img width="714" alt="スクリーンショット 2020-07-13 18.44.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/7c7803c3-9fa5-597c-1bff-7ba86b4d4e1b.png">

``add(3, 6)``の戻り値が10ではないからテストが通っていない、ということがわかるので、
>It is kind of White Box Testing

なのです。

# Integration Test

>combine modules in the application and test as a group to see that they are working fine

モジュールを組み合わせて正常に機能するかを示すということですから、ここでは``add``関数が組み合わさっている``total``関数に対するテストのことを指しています。

```App.test.js
import { total } from './App'

test('total', () => {
    expect(total(5, 20)).toBe('$25')
})
```

このテストは通ります。
テストコードはそのままで、``app関数``が意図していない動作になった時を確かめましょう。

```App.js
export const add = (x, y) => x - y  // 間違えて引き算にしてしまった

export const total = (shipping, subtotal) => {
    return '$' + add(shipping, subtotal)
}
```

<img width="711" alt="スクリーンショット 2020-07-13 18.57.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/577c576d-40b5-d25e-dcf3-1f19d8435e7e.png">

テストは通りません。

次に、テストコードはそのままで、``total``関数が意図していない動作になった時を確かめましょう。

```App.js
export const add = (x, y) => x + y

export const total = (shipping, subtotal) => {
    return '#' + add(shipping, subtotal) // 間違えて # にしてしまった
}
```
<img width="711" alt="スクリーンショット 2020-07-13 19.35.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/b4352964-79d8-1288-6de4-2855195a873f.png">


この場合もテストは通りません。

今回は簡単なコードなので、どちらの関数が意図しない動作になっているかは察せると思いますが、もっと大きなコードになっていくとわからなくなるでしょう。
内部的にどちらの関数にバグの責任があるか分からないため、
>It is kind of Black Box Testing

なのです。

# おまけ

今回の場合、``total``関数の仕事を、組み合わせるだけにしたら平和になる。(これが疎結合？)

```App.js
export const add = (x, y) => x + y
export const doller = () => '$'

export const total = (shipping, subtotal) => {
    return doller() + add(shipping, subtotal)
}
```

```App.test.js
import { add, doller, total } from './App'

test('add', () => {
    expect(add(1, 2)).toBe(3)
})

test('doller', () => {
    expect(doller()).toBe('$')
})

// addとdollerが通ったら必然的に通るから必要ない?
test('total', () => {
    expect(total(5, 20)).toBe('$25')
})
```
毎日SQLを手で実行して結果をエクセルに貼り付けて...なんてことしていませんか？　Pythonなら全自動でできます。

Pythonを最近勉強し始めたのですが、
PythonでSQL実行して結果をエクセル出力すると楽になると思ったのでまとめました。

コード50行くらいです。

# やること
1. PythonでSQLフォルダのSQLを順に実行
2. SQL実行結果をSQLと同じファイル名でエクセル出力
3. エクセルをZIPにまとめる
4. ファイルサーバに置く

# 試した環境
- Python3.8
- jupyter-notebook(Anacondaから)
- mysql

# 準備
- 実行したいSQLを〜.sqlの名前でフォルダにまとめて保存しておく
- 一部のPythonライブラリをimportしておく

# ソース／実行
```
import mysql.connector
import datetime
import glob
import os
import pandas as pd
import csv
import pyminizip
import pathlib
import shutil

def exec():

    # 1. PythonでSQL実行 ------------------------------------

    # DB接続
    conn = mysql.connector.connect(
       host = 'ホスト',
       port = 'ポート',
       user = 'ユーザ',
       password = 'パスワード',
       database = 'データベース' 
    )    
        
    # SQLファイル取得
    os.chdir("SQLファルダ")
    sql_file_list = glob.glob("*.sql")
    
    # フォルダ作成
    now = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    os.mkdir(now)

    # SQL実行
    for sql_file in sql_file_list:

        print(sql_file)        

        with open(sql_file, 'r') as f:
            sql_query = f.read()
    
        df = pd.read_sql_query(sql_query, con=conn) 

　　　　　# 2. 結果をエクセルで出力 ------------------------------------

        # エクセル出力の場合
        df.to_excel(now + "\\" + sql_file.replace('.sql', '.xlsx'), sheet_name=sql_file.replace('.sql', ''), index=False)
            
        # CSV出力の場合
        df.to_csv(now + "\\" + sql_file.replace('.sql', '.csv'), encoding="utf-8_sig", quoting=csv.QUOTE_NONNUMERIC, index=False)

    os.chdir(now)
        
    # 個別の編集があればここでやる

    # 結果ファイル取得
    result_file_list = glob.glob("*.xlsx")    

    # 3. ZIPにする ------------------------------------

    # 結果ファイル圧縮(日本語ファイル名非対応)
    file_path = []
    for i in range(len(result_file_list)):
        file_path.append('\\') 
    
    pyminizip.compress_multiple(result_file_list,file_path, now + '.zip','pass',0)
            
    # 4. ファイルサーバに置く ------------------------------------

    # 結果ファイルアップロード
    share = pathlib.WindowsPath(r'ファイルサーバ' + now + '.zip')
    shutil.copyfile(now + '.zip', share)
            
    # 切断
    conn.close()

# 実行
exec()

```
.NET Multi-platform App UI(通称.NET MAUI)でサポート予定のModel - View - Update (MVU)パターンとは

## はじめに

Microsoftが開催する開発者向けの大型イベント「Microsoft Build 2020」の中で、.NET Multi-platform App UI（通称 .NET MAUI）が紹介されました。紹介された内容は[こちら](https://www.infoq.com/jp/news/2020/07/maui-multi-platform-ui-dotnet/)を参照ください。

上記の紹介記事の中で私が気になったのは、掲題でも記しておりますが、以下の内容です。
> 最も関連性のあるもののひとつは、アプリケーションの開発パターンに関わるものだ — MAUIはModel-View-View-Model(MVVM、ReactiveUIを含む)とModel-View-Update(MVU、現在のXamarin.Formsではサポートされていない)をサポートする予定である。

MVVMパターンはWPFというWindowsアプリケーションの開発で用いられている開発パターンなので馴染みがあったのですが、MVUパターンに関してはそのようなものがあることすら知りませんでした。  
本記事ではそんなMVUパターンについて自分なりに調べた内容を紹介します。

## Model - View - Update (MVU)パターン

### 概要

MVUパターンはElmというプログラミング言語で導入された開発パターンです。参考文書にMVUパターンの紹介がありましたので、そちらを日本語に訳しつつ紹介しようと思います。

ElmでのModel - View - Updateパターンとは、以下で構成されたパターンとなります。

- Model : アプリケーションの状態
- View : 状態をHTMLに変換する方法
- Update : メッセージに基づき状態を更新する方法

そして、これらは以下の順序で関連しています。

1. 現在のアプリケーションの状態(Model)をHTML変換する(View)。
1. HTML変換されたページ(View)から受け取ったメッセージに基づき状態を更新する(Update)。
1. 更新された現在のアプリケーションの状態(Model)をHTML変換する(View)。
1. （上記の繰り返し）...

MVUパターンは遷移が単方向であり、私は非常にシンプルな開発パターンであると感じました。

### なぜ .NET MAUIでMVUパターンが採用されるのか

この理由について、[Microsoft開発者ブログ](https://devblogs.microsoft.com/dotnet/introducing-net-multi-platform-app-ui/?utm_source=vs_developer_news&utm_medium=referral)に記載されていました。
どうやら、以下の3点においてMVUパターンが優れているようです。

- データと状態の管理が単方向のフローとなるように促進できる
- 必要な変更のみをUIに適用できるため、素早く更新できる
- ホットリロードとの相性が良い

ホットリロードできると開発した見た目が即座に反映されるため、UIの見た目や使い勝手を確認しながら開発できます。現在のWPF開発でもホットリロードはできるのですが、相性が良いということはおそらく実行パフォーマンスがよくなったりするのだと推測されます。これは、開発者にとってかなりの利点だと思われます。

## おわりに

MVUパターンがなぜMVVMパターンに併せて採用されたのか知らなかったので、今回調べてみてかなり勉強になりました。
今後、MVUパターンに則ったコードを書いてみたいと思いました。またコードを書きましたら、記事で紹介しようと思います。

## 参考文書

- <https://elmprogramming.com/model-view-update-part-1.html>
- <https://guide.elm-lang.org/architecture/>
- <https://thomasbandt.com/model-view-update>
- <https://devblogs.microsoft.com/dotnet/introducing-net-multi-platform-app-ui/?utm_source=vs_developer_news&utm_medium=referral>
【cygwin】apache環境を作る

「 http://localhost/index.html 」で「Hello World!!」を見るくらいを目標とします。

# 参考にしたページ

- https://qiita.com/n-yamanaka/items/d9159e07b668d72649a1

# 追加インストールしたパッケージ

- httpd

# httpdをサービスに登録する
## スクリプト
```bash
#!/usr/bin/bash

NAME="apache2"
DESC="Cygwin Apache2"

readonly DAEMON_PATH="--path /usr/sbin/httpd"
readonly DAEMON_ARGS="--args -DFOREGROUND"
readonly DAEMON_EVAR="--env CYGWIN=server"
readonly DAEMON_EVAL="ntsec binmode server"
readonly DAEMON_WDIR="--chdir /var/empty"

########## FUNCTION

echodo()
{
        echo "########## CMD[$@]"
        "$@"
        return $?
}

########## MAIN

# stop and remove

SERVICE_NAME=`cygrunsrv --list | egrep -i ${NAME}`

if [ -z "${SERVICE_NAME}" ]
then
        true
else
        NAME=$SERVICE_NAME
        echodo cygrunsrv --list --verbose
        echodo cygrunsrv --stop $NAME
        echodo cygrunsrv --query $NAME --verbose
        echodo cygrunsrv --remove $NAME
fi

# install and start

echodo cygrunsrv --list --verbose
echodo cygrunsrv --install $NAME --desc "$DESC" \
        $DAEMON_WDIR $DAEMON_PATH $DAEMON_ARGS --env CYGWIN="$DAEMON_EVAL"
echodo cygrunsrv --query $NAME --verbose
while true
do
        echodo sleep 2
        if echodo cygrunsrv --start $NAME
        then
                echodo echo $?
                echodo cygrunsrv --list --verbose
                break
        fi
done

```

## サービス起動後の状況
```
Service             : apache2
Description         : Cygwin Apache2
Current State       : Running
Controls Accepted   : Stop
Command             : /usr/sbin/httpd -DFOREGROUND
Working Dir         : /var/empty
stdin path          : /dev/null
stdout path         : /var/log/apache2.log
stderr path         : /var/log/apache2.log
Environment         : CYGWIN="ntsec binmode server"
Process Type        : Own Process
Startup             : Automatic
Account             : LocalSystem
```

## スクリプトの補足
- cron環境を作る時に使ったスクリプトのパクリです。
    - 「--env」部分の共通化が可読性を下げるのでパクリで済ませています。
- CYGWIN環境変数について
    - 参考にした多くのページでは「server」のみの例が多いです。
    - ここでは全てを設定していますが、利用して不都合があれば変更します。
作業・仕事の中身に注目する（仕事の分析）

仕事を細かく作業ベースで分析すると、価値ある作業・付帯・ムダが見えてきます。
タスクの粒度を細かくすることでも同じように分析できます。
**正味**：価値ある作業
**付帯**：価値ある作業の前後に必要な段取り
**ムダ**：価値を生まないもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621379/8e4d30e5-1113-226f-5777-4b10c5ed310f.png)

会議・ミーティングはムダとします。
ホワイトカラーでは会議・ミーティングが多く仕事をしているように見えますが、深堀をして何故会議・ミーティングが必要となったのか？その真因を取り除くように改善を進めます。見える化は真因を取り除くことに貢献します。
ソフトウェア開発でのドキュメント作成は付帯であって、正味ではありません。正味はプログラムを製作している作業（コーディング）となります。デバックも付帯です。
stylish-haskellをBlockArgumentsに対応させる

# stylish-haskellをBlockArgumentsに対応させる

　次に同じことをするときのための自分用のメモ。

## 背景と問題

* 私はHaskellのフォーマッタにstylish-haskellを使っている。
* BlockArgumentsやDerivingVia拡張を使うと、stylish-haskellがこれをパースできなくなってしまう。

## 解決策

　ありがたいことに、解決策は[ここ](https://github.com/jaspervdj/stylish-haskell/issues/229#issuecomment-598839774)に書いてあった。

　グローバルへの汚染が最も少なそうな2番目の手順を試したところ、新たにインストールしたstylish-haskellは問題なく動いてくれた。
　他に書くべきこともないので、私がやった手順の日本語訳を置いておく。

> 手頃なプロジェクトの `stack.yaml` を編集して、`extra-dep`に`haskell-src-exts-1.23.0` を与える。その後、そのプロジェクト上で`stack install stylish-haskell`を実行する。

## 引用元

　引用元のURLはこちら。

Unable to parse `BlockArguments` syntax #229
https://github.com/jaspervdj/stylish-haskell/issues/229#issuecomment-598839774

　翻訳元のコメントはこちら。

> `stylish-haskell\ will work with this provided that you build it with `haskell-src-exts-1.23.0`. You can do this in a few ways:
>
> 1. Edit your global project (`~/.stack/global-project/stack.yaml`) to set `haskell-src-exts-1.23.0` as an `extra-dep`, and then do `stack install stylish-haskell`
> 2. Edit whatever project `stack.yaml` you have handy and set `haskell-src-exts-1.23.0` as an `extra-dep`, and then do `stack install stylish-haskell` from that project.
> 3. Run `stack exec --no-ghc-package-path -- cabal new-install stylish-haskell` which will automatically pull dependencies and use the GHC provided by `stack` (may require you to call `stack install cabal-install`)
> 
> `haskell-src-exts` is currently being held up by `haskell-names`, and I have opened a [PR](https://github.com/haskell-suite/haskell-names/pull/113) that should unblock `haskell-src-exts`.
RaspberryPiにchinachu導入

Raspberry PiにChinachuを導入しました。巷に無数にある記事なので、要点とつまづいた点を主に載せたいと思います。基本的な流れは[こちら](https://qiita.com/shotasano/items/3809b8f3e0b62d51d3c3)の記事に倣いました。


#環境
RaspberryPi3 Model B

```
$ cat /proc/cpuinfo | grep Revision
Revision        : a02082
```

#カードリーダー
物によって定義ファイルに型番の追記が必要みたいですが、私の環境では特に必要はありませんでした。`sudo pcsc_scan` でちゃんと読み込めてました。

```
$ lsusb
Bus 001 Device 004: ID 04e6:511a SCM Microsystems, Inc.
```

#MirakurunのインストールとNodeバージョン
当初Nodeのバージョンは6をインストールしたのですが、

```
$ node --version                     
v6.11.2
```

その後のMirakurunのインストールで失敗

```                                
 $ sudo npm install mirakurun -g --unsafe --production
 ～
Version: node@v6.11.2 [NG] Expected: ^8.9.4 < 9 || ^10.11.0 < 11   
↑ なにやらNodeのVersionがNGぽい
```

なんとなくver`10.11.0`以上が必要なのかと思い、[こちら](https://qiita.com/ktetsuo/items/71edd9af269d1fde6e2f)を参考にバージョン10にアップデート。ちなみに、後にChinachuもインストールするのですが、Chinachuのwikiでもバージョン10をインストールしているっぽい。

```
$ sudo node --version                
v10.16.3  
```

バージョン10にしたところMirakurunも無事インストール出来ました。

```
$ sudo npm install mirakurun -g --unsafe --production
 ～
Version: node@v10.16.3 [OK] 
～
Thank you for using mirakurun!                                                  
If you rely on this package, please consider supporting our open collective:    
> https://opencollective.com/Mirakurun/donate                                   
                                                                                
+ mirakurun@2.11.0  
```
# Chinachuのインストールと起動
Chinachuインストール後、pm2コマンドで起動を試みたのですが、`chinachu-operator`と`chicnachu-wui`が起動されず、sutatusが`errored`と表示されました。

pm2を介さないChinachuからの実行では問題ナシ。

```
$ ./chinachu service operator execute
$ ./chinachu service wui execute
```

pm2ログを確認したところnodeが見つからないというエラーメッセージを確認

```
$ sudo pm2 log PM2 
～
Error: spawn .nave/node ENOENT
```
[こちら](http://k-pi.hatenablog.com/entry/2017/07/30/151659)の記事によると、 
> RaspberryPiにChinachuを導入すると、.nave内にnodejsの実行ファイルが生成されない

とのことで見たところ、

```
$ ls -la .nave
total 52
drwxr-xr-x  5 pi pi  4096 Sep 19 16:51 .
drwxr-xr-x 15 pi pi  4096 Oct  1 17:14 ..
drwxr-xr-x  3 pi pi  4096 Sep 19 16:51 cache
drwxr-xr-x  3 pi pi  4096 Sep 19 17:05 installed
-rwxr-xr-x  1 pi pi 20591 May 19 05:57 nave.sh
lrwxrwxrwx  1 pi pi    50 Sep 19 16:51 node -> /home/pi/chinachu/.nave/installed/10.15.3/bin/node
lrwxrwxrwx  1 pi pi    49 Sep 19 16:51 npm -> /home/pi/chinachu/.nave/installed/10.15.3/bin/npm
drwxr-xr-x  2 pi pi  4096 Sep 19 16:51 src
-rw-r--r--  1 pi pi    42 Sep 19 16:51 .zlogout
-rw-r--r--  1 pi pi   707 Sep 19 16:51 .zshenv
``` 
`node`と`npm`が`/home/pi/chinachu/.nave/installed/10.15.3/bin/～`にリンクされているようですが、リンク先が空でした。ということでバイナリファイルをコピー。

```
cp /usr/bin/node /home/pi/chinachu/.nave/installed/10.15.3/bin/
cp /usr/bin/npm /home/pi/chinachu/.nave/installed/10.15.3/bin/
```
これで無事pm2から起動出来、録画サーバー完成！
※ちなみにChinachuインストール時、diskusageもインストール失敗してましたが特に影響はありませんでした。

#外付けHDDの追加
家にあったHDDを繋げてみたところ、`lsusb`では認識されるが、`df`コマンドではなぜか表示されず。

[こちら](https://qiita.com/marumen/items/de150089d95f52849e5b)の記事で「地味にハマッた」と書かれています。私もここで一番時間とお金を消費しました。
自分の作業を自動化する①

# ついに自分の作業の自動化に着手

RPAで自動化をやっている（やらされている）んですが、ついに自分のやっている作業の自動化に着手を開始しました。いやー、自分の作業の自動化をやらないでおじさんの作業の自動化をやっていることにものすごい疑問を持っていたんですよね…。

# 自動化する前の業務手順
以下の業務手順を自動化します。自分がやっていた作業の自動化なので、手順のヒアリングなどがなくものすごい楽に感じます。

- GoogleSpreadのデータをコピーして、エクセルに貼り付ける。これを各事業所の数だけ行う
- エクセルマクロを実行する

各事業所で毎日更新しているデータを一つのエクセルファイルに集約させる作業です。事業所によってはGoogleSpreadだったり、エクセルでデータを管理しています。各事業所のエクセルはエクセルマクロで集約を行っています。GoogleSpreadについては人力でコピー＆ペーストしています

## JobAutoでやりたいこと
JobAutoでやりたいことは以下の2つ。

### 各事業所のGoogleSpreadからデータをエクセルへコピー＆ペースト
Spreadの最終行がロボットが実行した日であれば、エクセルへコピー＆ペーストするようにします

### エクセルマクロ実行
エクセルマクロを実行するボタンをクリックします

## いざ作成

### GoogleSpread専用のアクションを使う
GoogleSpreadをアプリ操作でやる想定でいたので、ちょっと安定して動くのか不安でした。しかしGoogleSpread専用のあくしょんがあり、これがことのほか安定して動きそう。
JobAutoの機能はある程度抑えたつもりだったのですが、この機能は知りませんでした。

### エクセルマクロを直接実行する
従来の手順ではエクセルマクロをボタンを押して実行していました。エクセルマクロのプログラム名（関数名？）を指定することで、ボタンを押さなくてもマクロを実行できる機能があったのでこれを使いました。

## 出来上がったもの
出来上がったものが以下。各事業所ごとにSpreadからコピー＆ペーストしている個所をもっと工夫すればすっきりしたフローになる可能性を感じます。
![macro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660351/b536ca6d-a73d-2a80-23a4-47df6e829f06.png)

## 作成後の感想
GoogleSpreadの手順をアプリ操作を使わなくてもできたことが一番の収穫。GoogleSpread専用のアクションの存在を知らなかったので、もうすこしJobAutoをいろいろ触ってどんな機能があるのかを調べないといけないなと感じました。
Gitで作業開始前にブランチを切り忘れた時の対処法

##またやってしまった…
現在オリジナルアプリを開発中なのですが、最近gitにも慣れてきたせいか作業開始前によくブランチを切り忘れるので反省の念も込めて対処法を備忘録として書きます。

##解決方法
###まだコミットしていない場合
```
git checkout -b hoge(新しいブランチを作り切り替える）
```
これだけでOKです！
このままコミットを行えば**hoge**ブランチにコミットされます。
コミットされるまでブランチは分かれていない仕様のようです。ですので、変更しているファイルは変わらないです。

**hoge**ブランチから**master**ブランチに切り替えると作業開始前の綺麗な状態に戻ります。

###コミットしてしまった場合
以下の2つのコマンドを実行

```
#ブランチを作り移動
git checkout -b hoge
#masterをorigin/masterの状態へ戻す。
git branch -f master origin/master
```
-f(force)はあまり使いたくない場合（私はこっちを使います）

```
#masterブランチにいる状態で
git branch -m hoge
git branch master origin/master　#masterブランチがなくなったことで-fオプション無しでブランチが作れる
```

```git branch -m```, ```--move ```を使うと現在いるブランチをリネームすることができます。
ローカルのmasterがなくなるので、二つ目のコマンドでmasterブランチを再作成します。

##結論
リモートにpushする前に気付けば全然なんとかなる。（なお、反省してない模様）

##最後までご覧いただきありがとうございます。
もし間違い等ありましたらコメントからご指摘いただけますと幸いです。
【python】 末尾の特定の文字列を削除

# 末尾にある特定の文字列を削除したいとき

ある文字列Sに対し、Sの末尾にsという文字列があった場合、
末尾のsだけ削除する、というとき。

```python
S = 'abc123abcabc'
s = 'abc'

if S.endswith(s):
    S = S[:-len(s)]
print(S)  

# 出力結果: abc123abc
```

また、正規表現を用いて同様のことができます。

```python
import re

S = "abc123abcabc"
s = "abc$"

print(re.sub(search, "", string))

# 出力結果: abc123abc
```

こちらのほうがすっきりしていいかもしれません。

---

最初、rstrip()を使う方法も書いていましたが、
完全に勘違いしていたので、削除しました。
コメントありがとうございました。
日本一簡素なPythonのメモ（ダイアログボックスとか） 

#pythonでファイル操作するために学習したのでメモ。
####■ダイアログボックス、os.walk関数、pprintを使って選択したフォルダ内のファイルを一列に表示する
```python:
    #必要なモジュールのインポート
    import sys
    import os
    import tkinter,tkinter.filedialog
    #ファイルの表示を一列にするためにインポート
    import pprint

    #ファイルダイアログの作成
    root=tkinter.Tk()
    root.withdraw()#Tkinterのメインウィンドウが起動してしまうと処理が止まる場合があるので記述
    msg='フォルダを選択してください'
    my_path=tkinter.filedialog.askdirectory(title=msg)
    if (not my_path):
    print('ユーザがキャンセルしました')
    sys.exit()

    #OS.walk関数を使ってファルダ内のファイルを走査して表示
    for dirpaht,dirs,files in os.walk(my_path):
    for fname in files:
    pprint.pprint(fname)
```
###実行するとファイルダイアログが表示されますので、フォルダを選択します。
![pic_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205747/9ae79b75-b136-2956-c848-fb32d16e61e5.png)
###実行結果が表示されます。pprintを使うことで結果が一列で表示されます。
![pic_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205747/48d80e0a-0bcb-962a-e598-c3236747bb64.png)
Preg_match関数

こちらを参考に
[正規表現によるマッチング](https://www.php.net/manual/ja/function.preg-match)

```php
<?php

  $name = 'Name';
  $nickname = 'nickname';

  if (preg_match("/$name/i", $nickname)) {
    echo "OK";
  } else {
    echo "NO";
  } 
  
?>

```


$nameは$nicknameの中に含まれるのか
検証

$nameの後ろのiは大文字小文字を区別しない。

実行結果は

```
OK
```

---------------------------

```php
<?php

  $a = "Neverland Of Promise";
  $b = "neverland";

  if (preg_match("/\b$b\b/i", $a)) {
    echo $a . "\n";
  } else {
    echo "NG" . "\n";
  }
?>
```

\bで囲むとその単語のみマッチする
つまりこの例だとneverだけの場合反応するが、neverlandは反応しない

実行結果

```
Neverland Of Promise
```

------------------------
GitHub Enterprise版で自前で立てたサーバーのAPIを叩く

# 概要
GitHub API を叩くとき、 `https://api.github.com/～` といったURLにアクセスしますが、
Enerprise版で自前でサーバーを立てて独自ドメインで運営しており、どう置き換えればよいか分からなかったのでメモ。

# 認証API

```sh
curl -u "ユーザー名:パスワード" \
-d '{"scopes":["repo"],"note":"Hoge"}' \
https://自前のドメイン/api/v3/authorizations
```

こんな感じで、
`https://api.github.com/～` は基本的には `https://自前のドメイン/api/v3/～` に置き換えればOKな模様。

二要素認証を導入している場合は、

```sh
-H 'X-GitHub-OTP: 080673'
```

こんな感じでワンタイムパスワードをcurlのヘッダーオプションに指定。
(本当はワンタイムパスワードを使わずにトークン利用する方法もあると思うのですがうまくいかなかったので一旦)

```json
{
  "id": "xxx",
  "url": "https://ドメイン/api/v3/authorizations/xxx",
  "app": {
    "name": "Hoge",
    "url": "https://developer.github.com/enterprise/2.21/v3/oauth_authorizations/",
    "client_id": "00000000000000000000"
  },
  "token": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "hashed_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "token_last_eight": "bbbbbbbbb",
  "note": "Hoge",
  "note_url": null,
  "created_at": "2020-07-13T06:52:13Z",
  "updated_at": "2020-07-13T06:52:13Z",
  "scopes": [
    "repo"
  ],
  "fingerprint": null
}
```

このような結果が返ってくるので `token` をメモ。

# 目的のAPIにアクセス

今回は、[List pull requests](https://developer.github.com/v3/pulls/) のAPIでプルリクエスト一覧を取得しました。

URLが `https://api.github.com/repos/:owner/:repo/pulls` となっているため、前述の方法でURLを置き換え。

```sh
curl -H "Authorization: token さっき取得したtoken値" \
"https://ドメイン/api/v3/repos/オーナー/リポジトリ名/pulls?page=1&state=all"
```

結果を取得できました。
PynamoDB + Docker + DynamoDB Local設定 

# やりたいこと
- DockerでDynamoDB Localの環境構築
- PynamoDBでDynamoDB Local設定
- GUIでDynamoDB Localを表示

それでは行ってみよう！

## Dockerでローカルの環境構築

- docker-compose.ymlの作成

```
version: '3.7'
services:
  dynamodb-local:
    image: amazon/dynamodb-local
    container_name: dynamodb-local
    ports:
      - "8000:8000"
  app-node:
    depends_on:
      - dynamodb-local
    image: banst/awscli
    container_name: app-node
    ports:
     - "8080:8080"
    environment:
      AWS_ACCESS_KEY_ID: 'DUMMYIDEXAMPLE'
      AWS_SECRET_ACCESS_KEY: 'DUMMYEXAMPLEKEY'
    command:
      dynamodb describe-limits --endpoint-url http://dynamodb-local:8000 --region ap-northeast-1
```

- 起動する

```
docker-compose up -d
```




## PynamoDBでローカルDynamoDB設定

```
class Users(Model):
    """
    ユーザ情報
    """

    class Meta:
        table_name = "Users"
        region = 'ap-northeast-1'
        host = "http://localhost:8000"

    id = UnicodeAttribute(hash_key=True)
    password = UnicodeAttribute()
    month_password = UnicodeAttribute()
    token = UnicodeAttribute()
    login_date = UTCDateTimeAttribute()
    start_date = UTCDateTimeAttribute(default=datetime.now())
    account = AccountMap()
```
docker-compose.ymlに記載した

```
region = 'ap-northeast-1'
host = "http://localhost:8000"
```
この上記内容を入力

## GUIでローカルDynamoDB
- dynamodb-adminのインストール

```
npm install dynamodb-admin -g
export DYNAMO_ENDPOINT=http://localhost:8000
```
- 実行

```
dynamodb-admin
```

http://localhost:8001/
にアクセスすると、GUIでテーブルを確認できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166346/8a3ca149-22e2-8c10-a348-6db83c9dfa14.png)
DELETEメソッド実行後のリダイレクトでNo route matches [DELETE]となってしまう

非同期処理で削除処理を行った後、リダイレクトを行うとメソッドがGETではなくDELETEとなってしまい正常にリダイレクトされない現象が発生したためメモ。

# 発生した状況
```delete.js
// 一部抜粋
$.ajax({
  type: 'DELETE',
  url: '/posts/destroy_post',
  dataType: 'json',
  data: {
    post_id: $(this).data('post-id')
  }
}).done(function (data, status, xhr) {
  // 処理
});
```

```posts_controller.rb
  # 一部抜粋
  def destroy_post
     # 処理

    redirect_to post_index_path
  end
```

```
// 発生エラー
ActionController::RoutingError (No route matches [DELETE] "/post"):
```

# 改善策
```posts_controller.rb
  # 一部抜粋
  def destroy_post
     # 処理

    redirect_to post_index_path, status: 303
  end
```

上記のように｢status: 303｣と記載をすることで改善。

http://api.rubyonrails.org/classes/ActionController/Redirecting.html

> If you are using XHR requests other than GET or POST and redirecting after the request then some browsers will follow the redirect using the original request method. This may lead to undesirable behavior such as a double DELETE. To work around this you can return a 303 See Other status code which will be followed using a GET request.

> GETまたはPOST以外のXHRリクエストを使用していて、リクエストの後にリダイレクトしている場合、一部のブラウザは元のリクエストメソッドを使用してリダイレクトに従います。これにより、二重DELETEなどの望ましくない動作が発生する可能性があります。これを回避するには、GETリクエストを使用して追跡される303 See Otherステータスコードを返すことができます。

上記のように二重DELETEが発生していたと思われる。
引数にStatusコード303を指定することにより、回避することができるようです。

# 参考
[Rails Redirect After Delete Using DELETE Instead of GET
](https://stackoverflow.com/questions/14598703/rails-redirect-after-delete-using-delete-instead-of-get)

以上です。
いいねやQiitaやTwitterのフォローいただけると励みになります！
他にも方法がありましたら、コメントお待ちしております。
宜しくお願いします〜
Rust で JSON ファイルを読む

フォルダー構造

```text
$ tree -L 2
.
├── Cargo.lock
├── Cargo.toml
├── cities.json
├── src
│   └── main.rs
└── target
    └── debug
```

```text:Cargo.toml
[package]
name = "json_read"
version = "0.1.0"
edition = "2018"

#

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```

```rs:src/main.rs
// --------------------------------------------------------------------
/*
	json_read.rs

						Jul/15/2020
*/
// --------------------------------------------------------------------
use std::env;
use std::fs::File;
use std::io::BufReader;

// --------------------------------------------------------------------
fn main() -> std::io::Result<()> {
	eprintln!("*** 開始 ***");

	let args: Vec<_> = env::args().collect();
    
	let ref fname_in = args[1];

	let file = File::open(fname_in).unwrap();
	let reader = BufReader::new(file);

	let json: serde_json::Value = serde_json::from_reader(reader)?;

	let obj = json.as_object().unwrap();

	for (key,value) in obj.iter() {
		println!("{}\t{}\t{}\t{}",key,value["name"],
			value["population"],value["date_mod"]);
		}

	eprintln!("*** 終了 ***");

	Ok(())
}

// --------------------------------------------------------------------
```

```json:cities.json
{
  "t0921": {
    "name": "宇都宮",
    "population": 41295,
    "date_mod": "2003-8-12"
  },
  "t0922": {
    "name": "小山",
    "population": 38756,
    "date_mod": "2003-5-15"
  },
  "t0923": {
    "name": "佐野",
    "population": 71294,
    "date_mod": "2003-6-8"
  },
  "t0924": {
    "name": "足利",
    "population": 27138,
    "date_mod": "2003-7-21"
  },
  "t0925": {
    "name": "日光",
    "population": 74682,
    "date_mod": "2003-4-19"
  },
  "t0926": {
    "name": "下野",
    "population": 82951,
    "date_mod": "2003-10-14"
  }
}
```

コンパイル

```bash
cargo build
```

実行

```text
$ cargo run cities.json 
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/read cities.json`
*** 開始 ***
t0921	"宇都宮"	41295	"2003-8-12"
t0922	"小山"	38756	"2003-5-15"
t0923	"佐野"	71294	"2003-6-8"
t0924	"足利"	27138	"2003-7-21"
t0925	"日光"	74682	"2003-4-19"
t0926	"下野"	82951	"2003-10-14"
*** 終了 ***
```

## 確認したバージョン

```text
$ rustc --version
rustc 1.75.0 (82e1608df 2023-12-21) (built from a source tarball)
```
pythonのtqdmで進捗バーが表示されない時の対処法

pythonのtqdmを使えば進捗バーが表示されます．

```python
from tqdm import tqdm
import time

for i in tqdm(range(10)):
    time.sleep(0.1)
```

```text:実行結果
100%|██████████████████████████████████████████████████████████████████████████████████| 10/10 [00:01<00:00,  9.75it/s]
```

ただ，例えば次のような場合は進捗バーはなぜか表示されません．

```python
from tqdm import tqdm
import time

for i in tqdm(reversed(range(10))):
    time.sleep(0.1)
```

```text:実行結果
10it [00:01,  9.75it/s]
```

この場合，次のようにすれば解決できました．

```python
from tqdm import tqdm
import time

for i in tqdm(reversed(range(10)), total=10):#totalでfor文の繰り返し回数を指定してあげる
    time.sleep(0.1)
```

```text:実行結果
100%|██████████████████████████████████████████████████████████████████████████████████| 10/10 [00:01<00:00,  9.77it/s]
```
【Solidity】関数修飾子(modifier)の使い方

ある関数（またはメソッド）を実行する前に必ず実行しておきたい処理があるケースがたまにあります。
Railsで言えばbefore_actionのようなものでしょうか。

Solidityでこれを実現するには関数修飾子(modifier)を使用します。

関数修飾子は直接呼び出すことはできず、関数定義の最後に関数修飾子の名前を指定することで、その関数が実行される前に指定した関数修飾子が実行されることになる。

と言っても分かりにくいので、例を以下に記載します。

# 引数がない場合

まずは関数修飾子(modifier)を定義します。
こちらはOpenZeppelinというSolidityライブラリのOwnableコントラクトの一部を抜粋したものです。

```Solidity:
contract Ownable {
  address public owner;

  // これはコンストラクタ。コントラクトが最初に作成された時に、1度だけ実行される
  function Ownable() public {
    owner = msg.sender;
  }

  // 関数修飾子の定義。関数を実行したアドレスがオーナーのものであるかをチェックしている
  modifier onlyOwner() {
    require(msg.sender == owner);
    // ここに到達すると呼び出し元の関数に戻ってコードが実行される
    _;
  }
}
```

関数修飾子が定義されたので、この関数修飾子を使用してみます。

```Solidity:
contract MyContract is Ownable {
  mapping(address => uint) mynumbers;

  // この関数のコードを実行する前に関数修飾子'onlyOwner'が実行される
  function setMyNumber(uint _number) external onlyOwner {
    mynumbers[msg.sender] = _number;
  }
}
```

ここではsetMyNumber関数に関数修飾子'onlyOwner'を付けています。
そのため、setMyNumber関数が呼ばれる前にOwnableコントラクトの関数修飾子onlyOwnerが実行されます。

よってこの例ではsetMyNumber関数はOwnableコントラクトを作成したオーナーしか実行できないことになります。

このように関数を実行できる人を限定したいとか、関数実行前に実行しておきたい処理は関数修飾子として定義しておくと何かと便利です。

# 引数がある関数修飾子

関数修飾子は引数を受け取ることもできます。
引数を受け取るパターンも例を記載しておきます。

```Solidity:
// ユーザーの年齢を格納する
mapping (uint => uint) public age;

// ユーザーの年齢が一定の年齢以上であることをチェックする関数修飾子
modifier checkAge(uint _age, uint _userId) {
  require (age[_userId] >= _age);
  _;
}

// checkAgeで20歳以上であることをチェックしてから関数のロジックを実行する
function canDrink(uint _userId) public checkAge(20, _userId) {
  // 関数のロジック
}
```

この例の通り、canDrinkで受け取った引数を関数修飾子checkAgeの引数にそのまま渡すことができます。

事前に引数の値チェックをしておきたいケースなどでも使えそうですね。
PynamoDB でテーブル作成・検索・作成

# やりたいこと
- DynamoDBをMACから触れるようにする
- pynamoDBでテーブル操作する

## 前提条件
- AWS Access Key ID と AWS Secret Access KeyはGET済み

行ってみよう！

## DynamoDBをMACから触れるようにする
#### 公式サイトからAWS CLI バージョン 2 のインストール
1. ブラウザで、macOS pkg ファイルをダウンロードします: https://awscli.amazonaws.com/AWSCLIV2.pkg
2. ダウンロードしたファイルをダブルクリックして、インストーラを起動します。
3. 画面上の指示に従ってください。AWS CLI バージョン 2 は以下の方法でインストールできます。
（参考）
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-mac.html
これで、コマンドでAWSを触れるようになりました。


#### aws configure で AWSと連携
```
(venv) mbp:wanted user$ aws configure
AWS Access Key ID [None]: ABCDEFGHIJGLMNOPQRSTUVWXYZ
AWS Secret Access Key [None]: SECRETKEYSECRETKEYSECRETKEYSECRETKEY
Default region name [None]: ap-northeast-1
Default output format [None]: 
```
対話式で、アクセスキーとシークレットキーを入力すれば連携が完了

## テーブルの作成
```
from datetime import datetime

from pynamodb.attributes import UnicodeAttribute, UTCDateTimeAttribute, MapAttribute, NumberAttribute
from pynamodb.models import Model


class AccountMap(MapAttribute):
    """
    アカウント情報
    """
    price = NumberAttribute(null=True)
    search_limit_num = NumberAttribute(null=True)
    url = UnicodeAttribute(null=True)


class Users(Model):
    """
    ユーザ情報
    """

    class Meta:
        table_name = "Users"
        region = 'ap-northeast-1'

    id = UnicodeAttribute(hash_key=True)
    password = UnicodeAttribute()
    login_date = UTCDateTimeAttribute()
    start_date = UTCDateTimeAttribute(default=datetime.now())
    account = AccountMap()


# ユーザテーブルの作成
if not Users.exists():
    Users.create_table(read_capacity_units=1, write_capacity_units=1, wait=True)
```
こんな感じで、作れる。Django感、半端ないです＾＾

## 検索
### query
キーを指定してから、検索

```
def get_user_info(user_id, password, month_password):
    """
    パスワード認証
    :param user_id:
    :param password:
    :param month_password:
    :return:
    """
    # TODO トークンの取得
    token = "local"

    # ユーザIDとパスワードと今月のパスワードとトークン
    for user_data in Users.query(user_id, (Users.password == password) & (Users.month_password == month_password) & (
            Users.token == token)):
        return user_data

    return None

```
queryで検索

### scan
キーを指定せずに、検索

```
Users.scan(Users.id==user_id)
```

### 保存
```
    # データの作成
    users = Users('onehundred')
    users.password = "password"
    users.token = "local"
    users.month_password = "month_password"
    users.login_date = datetime.now()
    users.start_date = datetime.now()
    users.account = {
        "price": 1000,
        "search_limit_num": 10,
        "pay_pal_url": "https://paypal.com",
    }
    users.save()
```
よく使うgitコマンドまとめ

SourceTreeを卒業し、コマンド操作でgitを利用する事があったので軽くメモ。

## ローカル編
#### リポジトリのダウンロード

    $ git clone https://〜〜〜 # リポジトリのURL

#### ブランチの確認
自分の使用しているブランチの確認と、ブランチ一覧を表示する。

    $ git branch

#### ブランチの切り替え

    $ git checkout 切り替え先のブランチ名

#### ブランチの作成
現在いるブランチにて以下のコマンドで新しいブランチを派生させる。
個人で使うには自由、共同開発現場では`git-flowチートシート`の内容が一般的。

    $ git checkout -b ブランチ名

#### ブランチの削除
削除するブランチから別ブランチへ移動しておくこと。

    $ git branch -D ブランチ名

#### リモートとローカルの同期
以下のコマンドには`git fetch`も含まれている。

    $ git pull

#### 差分の確認
差分ファイルを表示する。

    $ git status

ファイル内の差分表示する。（ファイルパスは`git status`で表示されたもの）

    $ git diff [ファイルパス]

`space`キーで進む。
`q`キーで確認終了。

#### 差分の取消
変更前の状態に戻す。

    $ git checkout [ファイルパス]

`全てのファイル`の差分を取り消す。

    $ git checkout . # ピリオドを使用する

#### 変更（差分）をindexに保持
差分ファイルを`indexに保持`する。

    $ git add [ファイルパス]

`-A`オプションは差分が出ている`全てのファイル`を指定する。

    $ git add -A

#### 変更をコミットする
`indexに保持した差分`をブランチに記録する。

    $ git commit -m "hogehoge"

#### コミット履歴の確認
コミットIDとコミットした際にコメントを付けていれば、コメントが確認できる。

    $ git log

#### コミットの取消

直前のコミットを削除し、差分を残したままにする。

    $ git reset --mixed HEAD^

#### コミットの削除

`git log`で表示させたコミットIDのうち、指定したコミットIDを削除する。

    $ git reset --hard コミットID

#### ローカルからリモートへPUSHする
originはとりあえず固定でリモートを指すものとしておく。

    $ git push origin ブランチ名

##### `強制`PUSH
リモートに同名のブランチがあるだけ場合はリモートのブランチを削除後に普通にPUSHする方が良いが必要に応じて使用。

    $ git push -f origin ブランチ名

#### 他ブランチから差分をマージで取り込む
開発中のブランチにいる状態でmasterを指定すればmasterの差分が取り込まれる。
コンフリクトが起こったら修正する。
`cherry-pick`や`rebase`という手段もあり。

    $ git merge 取り込むブランチ名 # 今checkoutしているブランチに取り込まれる

#### タグを付ける

    $ git tag タグ名

#### タグにコメント（注釈）を付ける

    $ git tag -a tag -m "hogehoge"

#### タグのPUSH

    $ git push origin タグ名

#### 全タグのPUSH

    $ git push origin --tags

#### タグを削除

    $ git tag -d ダグ名

#### タグ一覧

    $ git tag

## リモート編
#### リモートブランチの削除
ブランチ名の前に`:`が必要。ローカルのどのブランチで実行してもOK。

    $ git push origin :ブランチ名



#### リモートのタグを削除
タグ名の前に`:`が必要。

    $ git push origin :タグ名



## 初期設定
#### 初期化
gitが設定されていないディレクトリで以下を実行するとgitが適用される。

    $ git init

初期化後に`ブランチを作成(master)`、`変更をindexに保持`、`ブランチにコミット`することによって、最初の`repositoryが作成`される。
初期化した後にファイルの変更を行うと`差分`が生まれる。

#### 履歴に残る名前を設定

    $ git config --global user.name "自分の名前"
    $ git config --global user.email "xxxxx@xxxxxxx.co.jp"

## その他
#### Serverにrepositoryを用意
Server内でgit用ディレクトリ（xxxx.gitと名前を付ける）に移動し、以下のコマンドを実行。

    $ git init --bare --shared

#### ローカルとリモートの紐付け
ローカルで行う。
`domain`はIPでもURLでも。
`xxxx.git`はServer内のgitディレクトリのフルパス。

    $ git remote add origin https://[user名@]domain:xxxx.git

#### 子リポジトリの読み込み

    $ git submodule hogehoge

#### 子リポジトリの更新

    $ git submodule update

#### 【参考】

#####originて何？
http://dqn.sakusakutto.jp/2011/10/git_push_origin_master.html
一発でGitHub/Qiita/Teratail/StackOverflow/Googleなど全てのサイトでダークテーマを使う方法

## はじめに
プログラミングしている皆さんはIDEとかコードエディタで背景を黒にする「ダークテーマ」使っている方多いですよね？
私もその一人で、VisualStudioCodeのようなコードエディタだけでなく、EvernoteなどのノートアプリやMac, iPhoneのOS設定に至るまでダークモードにして身の回りを漆黒に染めています。(厨二病感)

最近だとwebサービスもダークモードに対応するコンテンツが増えてきました。
有名所だとYouTubeやGoogleKeepなどが挙げられますね。
しかし、まだまだ大多数のwebサイトの背景は眩しいままです。
私のような闇に生きるダークモード信者は、目が眩しさで焼ける苦しみに耐えながら日々生活して(ググって)います。

## ダークテーマに対応していないwebサイトに一括で適用する方法
プラウザはGoogleChromeを想定しています。
方法は大きく分けて２つあります。

- GoogleChromeのflagsで設定する
- Chrome拡張機能を適用する

Chrome78から chrome://flags の設定項目で強制ダークモードにできるようになりましたが、サイトによっては白と黒以外の色が暗くて見ずらいとか、サイトごとにON/OFFを設定できないとか、かゆいところに手が届かない感じが残っています。
したがって、本記事では**拡張機能を使います**

## 強制ダークモード拡張機能 "Dark Reader"
Chromeウェブストアで公開されています。
[Dark Reader - Chrome ウェブストア](https://chrome.google.com/webstore/detail/dark-reader/eimadpbcbfnmbkopoojfekhnkhdbieeh?hl=ja)

公式サイト↓
[Dark Reader](https://darkreader.org/)

他にもサイトに強制ダークモードを適用する拡張機能はありますが、筆者が使った感じでは一番表示が安定していました。
サイトごとにコントラストなどの設定やダークモードのON/OFFを覚えさせておくと、次回アクセスしたときに自動的にその設定で表示してくれるのは素晴らしいですね。

Chromeに追加すると、アドレスバーの右にアイコンが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185108/ce169f96-3980-6010-e794-d2b559ff1617.png)

それをクリックすると、このような設定画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185108/b265b10c-6081-0d6a-1f64-fad59c2e1187.png)


オープンソースで開発されています。
[GitHub - darkreader/darkreader: Dark Reader Chrome and Firefox extension](https://github.com/darkreader/darkreader)

筆者は試してませんが、FirefoxやSafariにも対応しているようです。

### 適用結果
設定はデフォルトのままですが、サイト側で対応しているのでは？と思ってしまうくらい表示がきれいです。
#### GitHub
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185108/2c0a0dbd-7870-4652-3380-dd3e31aeb014.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185108/68b21282-8375-ad76-4eb8-d7ac16c5311e.png)


#### Qiita
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185108/246002c1-3e3f-4655-4065-e9807618a3f8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185108/b333b619-2b5d-49ab-9011-b2702009031c.png)


#### Google
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185108/829cffec-cc8d-d7c8-ab44-fd9f9bec9507.png)

#### Teratail
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185108/5a832536-ec84-3cc3-2677-6d654813e1be.png)


## それでもダークテーマにならないサイトへの対処法
Google検索結果のpdfでも使いたい場合はキャッシュを読み込むとhtmlで表示されるので、ダークモードが適用されます。
Biz メール＆ウェブビジネスでgoogleの検索ロボットをブロックしてるなんて（503エラー）

もうメモがてら

#Biz メール＆ウェブビジネスはデフォルトでgoogleの検索ロボットをブロックしてる？

Google、Facebookのツール系がすべて503
検索にものらない

503
503
503...

問い合わせたところ、
**海外IPフィルタリング機能の、
ウェブ（80/443）の制限を無効として改善されるかどうか
お試しいただけますでしょうか。**
とのこと。

##設定
管理画面の「システム」→「IPアクセス制限」「ウェブ[ポート番号:80/443]」のチェックを外して更新

##まとめ
最初からこの設定になっているかわかりませんが、
**Biz メール＆ウェブビジネスでwebサイトを作成する際は注意**が必要だと思います。
ブロックプログラムで遠隔地IoTを行う



obnizのブロックプログラムは複数台のobnizを簡単に扱うことができますが、あんまりみんな使ってないなぁと思うので書いてみます。


<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">obniz2台連携をブロックプログラムで。 <a href="https://t.co/3ln2W9DVcn">pic.twitter.com/3ln2W9DVcn</a></p>&mdash; kido (@9wick) <a href="https://twitter.com/9wick/status/1282598853586239488?ref_src=twsrc%5Etfw">July 13, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


↑こういうのをブロックプログラムで作れるよ　というお話です


# ブロックの作り方

ブロックプログラムでは最初に接続するブロックを書きますが、


![スクリーンショット 2020-07-13 17.54.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/dda2b9eb-6ea2-1e7e-48bf-c0c50b17a337.png)

実はこのブロック、２つつけることもできます。
![スクリーンショット 2020-07-13 17.55.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/c829f9fd-0224-e3a4-5b4d-8031392328b9.png)


そして下のブロックの"obniz"となっているところを選択して

![スクリーンショット 2020-07-13 17.55.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/f39a4764-4631-b031-49ab-52de04251c61.png)

New obniz variableから新しくobnizBをつくると
![スクリーンショット 2020-07-13 17.57.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/ba082bb7-9e3e-1ad4-a07b-cb2348134747.png)

obnizBが選べるようになります。
![スクリーンショット 2020-07-13 17.55.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/59cfbf99-e52f-e6cc-3dbe-ff93059b4af2.png)


obnizIDも変えたらこれで２つのobnizを同時に使うことができるようになりました。

![スクリーンショット 2020-07-13 17.55.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/a4314e28-dd2a-b522-cd97-3b8737d50c7e.png)



# たとえば

たとえば、それぞれのobnizにパーツを接続して、片方のobnizのセンサーデータが条件を満たしたら、もう反対のobnizにくっついているモーターを回す　ということもできてしまいます

![スクリーンショット 2020-07-13 18.02.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/234a04c1-c419-5cda-3cd5-66bde3709faa.png)


<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">obniz2台連携をブロックプログラムで。 <a href="https://t.co/3ln2W9DVcn">pic.twitter.com/3ln2W9DVcn</a></p>&mdash; kido (@9wick) <a href="https://twitter.com/9wick/status/1282598853586239488?ref_src=twsrc%5Etfw">July 13, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


※赤いブロックのモーターは obnizに、青いブロックのセンサはobnizBにつながっています。
違うobnizにつながっているのがポイントです


一つのロジックで動かせるので、わかりやすいですよね。
２つのobnizはどれだけ離れていてもいいので、アメリカにセンサをおいて、日本でモータを動かす　なんてこともブロックプログラムでできてしまいます。