2021/12,江端さんの技術メモ

「ファイル」 → 「フォルダを開く」でフォルダを選択すれば、settings.jsonが出てこなくなる

フォルダの中に、".vscode"のディレクトリがって、その中には、以下のファイルが入っていることも必要(多分)

Visual Studio Code C/C++ 検討中

 

2021/12,2021/12,江端さんの忘備録,江端さんの技術メモ

Open Street Map(以下OSMといいます)とは、「自由に利用でき、なおかつ編集機能のある世界地図を作る共同作業プロジェクト」のことです。

Open Street Map (OSM) is a collaborative project to create a freely available, yet editable, map of the world.

一般的には、"xxxxx.osm"ファイルという名前の地図情報ファイルの意味で使われることが多いです。

In general, it is often used to mean a map information file named "xxxxxx.osm" file.

このようなomsファイルは、地図を使った交通シミュレーションを行う研究員にとっては、大変助かります。

These oms files are very helpful for researchers who are working on map-based traffic simulations.

しかし、OSMの地図は、世界中の人達の協力によって作られているものですし、そもそも、地図は常に拡張や変更を続けるものです。

However, OSM's maps are made with the cooperation of people from all over the world, and in the first place, maps are always expanding and changing.

「完璧な地図」などはありません。

There is no such thing as a "perfect map.

特に、自分の研究でomsファイルを使う場合、必要に応じて地図情報を正しく修正したいことがあります。

Especially when using oms files in my own research, I may want to modify the map information correctly if necessary.

-----

そんな訳で、今朝から、OSMの地図の編集を試みています。

That's why I've been trying to edit the OSM map since this morning.

以下は、横浜国立大学の敷地内の地図ですが、この中に、「自動車が入れる道」が記載されていなかったので、先程追記してみました。

The following is a map of the grounds of Yokohama National University, which I have just added to the map because it did not include a "car road".

なぜ、私が大学キャンパスの道を知っているのか ―― そりゃもう、このキャンパスの中を、何百回、自動車と足で走り回り、GPSロガーでデータを取りまくったことか、分かりません ―― 仕事(屋外実証実験)で。

How do I know my way around a university campus? Well, I can't tell you how many times I've driven around this campus by car and foot, taking data with my GPS logger for my work (field demonstration).

-----

ところで、今朝の私のこの修正が、ボタン一つでOSM地図情報に登録されてしまって、唖然としています。

By the way, I was stunned to see that this correction of mine this morning was registered in the OSM Map Information with the click of a button.

修正後は、私の記載した地図が、世界中で反映されてしまうことになります。

After the revision, the map I described will be reflected all over the world.

―― 私の過失、または、悪意で、地図を改竄(かいざん)してしてしまったらどうするんだ?

"What if the map is tampered with due to my negligence or malicious intent?"

と、かなり不安な気持ちになってきました。

I came to feel quite uneasy.

なにしろ、今回の修正は、私の初めてのトライアルですので。

After all, this is my first trial with this modification.

そのような場合でも、多分、『だれかが私の改竄を修正する』、そして、『私が間違いを続ければ、私をOSMメンバから除名する』と期待しているのですが ――

Even in that case, I'm hoping that maybe "someone will correct my falsification" and "if I continue to be wrong, they will expel me from OSM membership" -- but I'm not sure.

それにしても、「自由に利用でき、なおかつ編集機能のある世界地図を作る共同作業プロジェクト」って凄いなぁ、と実感しています。

Anyway, I really feel that "a collaborative project to create a freely available, yet editable world map" is a great idea.

=====

実行手順

Step.1 https://www.openstreetmap.org/ から、「ユーザ登録」

Step.2 ユーザ登録します。

私の場合、サードパーティ認証にGoogleのログインを使うことにしました。

その後は、ガイダンス画面に入るので、そこで一通り勉強してから、編集作業をします(今日は割愛します)。

以上

 

 

2021/12,江端さんの技術メモ

エージェントオブジェクトの消滅方法に着目したコード

参照させて頂いたページ https://qiita.com/yoshinori_hisakawa/items/a6608b29059a945fbbbd

// https://qiita.com/yoshinori_hisakawa/items/a6608b29059a945fbbbd

package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

func main() {
	wg := sync.WaitGroup{}

	wg.Add(1)
	go grandparent(&wg)

	//time.Sleep(10 * time.Second)
	wg.Wait()
}

func grandparent(wg *sync.WaitGroup) {
	// contextを生成
	defer wg.Done()
	ctx := context.Background()

	// 親のcontextを生成し、parentに渡す
	ctxParent, cancel := context.WithCancel(ctx)
	go parent(ctxParent, "Hello-parent")

	// parentのcontextをキャンセル。mainを先に終了させないように1秒待ってから終了
	cancel()
	time.Sleep(1 * time.Second)
	fmt.Println("grandparent end")
}

func parent(ctx context.Context, str string) {
	// parentからcontextを生成し、childに渡す
	childCtx, cancel := context.WithCancel(ctx)
	go child(childCtx, "Hello-child")
	defer cancel()
	// 無限ループ
	for {
		select {
		case <-ctx.Done():
			fmt.Println(ctx.Err(), str)
			return
		}
	}
}

func child(ctx context.Context, str string) {
	// 無限ループ
	for {
		select {
		case <-ctx.Done():
			fmt.Println(ctx.Err(), str)
			return
		}
	}
}

// context canceled Hello-child
// context canceled Hello-parent
// grandparent end

2021/12,江端さんの技術メモ

私の作るエージェントプログラムは、エージェントが数千~数万回のレベルで発生ー消滅をするものなので、エジェントの消滅時に、確実にgoroutineを消滅させる必要があります。

しかし無限ループでイベント待ちをしているgoroutineを止める方法で、苦慮してきたのですが、問答無用でgoroutineを潰す、context.Contextというものを見つけて ―― 『これまでの苦労は一体なんだったんだ』と思っています。

まあ、こういうことって、結構ありますけどね。

package main

import (
	"context"
	"fmt"
	"time"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	go loop(ctx)

	// 2.5秒待つ
	time.Sleep(2500 * time.Millisecond)

	// ここで loop() を止める
	cancel()

	// 2回呼び出しても大丈夫
	cancel()

	println("finish")
}

// 無限ループする関数
func loop(ctx context.Context) {
	for {
		fmt.Println("test")
		time.Sleep(time.Second)
	}

}

親から子どもを一斉に消滅させる方法については、明日、片付けます。

なお、こっちの defer cancel()を使う方がスマートです。

package main

import (
	"context"
	"fmt"
	"time"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	go loop(ctx)
	defer cancel()

	// 2.5秒待つ
	time.Sleep(2500 * time.Millisecond)

	println("finish")
}

// 無限ループする関数
func loop(ctx context.Context) {
	for {
		fmt.Println("test")
		time.Sleep(time.Second)
	}

}

 

 

 

 

2021/12,江端さんの技術メモ

週末使って、色々試した結果、「チャネルを返り値とするサブルーチンは、fatal error: all goroutines are asleep - deadlock! となる」ということでした。

# まあ、 select-caseで、メソッドを直接使いたい、という変則的な使い方でしたので、仕方ありませんが、

package main

import "fmt"

func channel_test() chan int {
	ch := make(chan int)
	ch <- 1
	return ch
}
func main() {

	v := channel_test()
	fmt.Println(v)

	// go channe_test()とすれば動く

}

こんな使い方を想定していました。

for{
		select{
		case v:= <-channel_test():
			// do something 
		}
	}

続報:

ネットの質問版で質問してみたら、

ch := make(chan int)を、ch := make(chan int, 1)としたら動くよ、と教えて頂き、動作確認できました。

お詫びして訂正致します。
package main

import (
	"fmt"
	"time"
)

func channel_test() chan int {
	ch := make(chan int, 1)
	ch <- 1
	return ch
}
func main() {

	v := channel_test()
	fmt.Println(v)

	// go channe_test()とすれば動く

	for {
		select {
		case v := <-channel_test():
			fmt.Println("case v := <-channel_test():", v)
		}
		time.Sleep(time.Second)
	}

}
江端

2021/12,江端さんの技術メモ

これは、結構オーソドックスな手法で、いろいろなところに使われています。

/*
	お題: personが終了したらsubPerson1も subPerson2も強制的に終了させるには?
*/

package main

import (
	"fmt"
	"sync"
	"time"
)

func subPerson1(i int, wg *sync.WaitGroup, ch chan struct{}) {
	defer wg.Done()

	<-ch // close(ch)が発行されるまでロック (普通はselect待ちにする)
	fmt.Println("		End of sub_person1(", i, ")")

}

func subPerson2(i int, wg *sync.WaitGroup, ch chan struct{}) {
	defer wg.Done()
	<-ch // close(ch)が発行されるまでロック (普通はselect待ちにする)
	fmt.Println("		End of sub_person2(", i, ")")
}

func person(i int, wg *sync.WaitGroup) {
	fmt.Println("	Start... person(", i, ")")
	defer wg.Done()

	subWG := sync.WaitGroup{}

	subWG.Add(2)
	ch := make(chan struct{})
	go subPerson1(i, &subWG, ch)
	go subPerson2(i, &subWG, ch)

	time.Sleep(10 * time.Second)
	close(ch)

	subWG.Wait()

	fmt.Println("	End... person(", i, ")")
}

func main() {
	fmt.Println("start... main()")
	wg := sync.WaitGroup{}
	for i := 0; i < 5; i++ {
		wg.Add(1) // goルーチンを実行する関数分だけAddする

		go person(i, &wg)
	}

	wg.Wait()
	fmt.Println("end of ... main()")
}

出力結果はこんな感じです。
ちょっと変な感じがしますが、多分Printlnを記載している時間タイミングに因るものだろう、と思います。

$ go run main.go
start... main()
        Start... person( 4 )
        Start... person( 2 )
        Start... person( 3 )
        Start... person( 0 )
        Start... person( 1 )
                End of sub_person2( 2 )
                End of sub_person2( 0 )
                End of sub_person1( 0 )
        End... person( 0 )
                End of sub_person2( 4 )
                End of sub_person1( 4 )
        End... person( 4 )
                End of sub_person2( 3 )
                End of sub_person1( 3 )
        End... person( 3 )
                End of sub_person1( 2 )
        End... person( 2 )
                End of sub_person2( 1 )
                End of sub_person1( 1 )
        End... person( 1 )
end of ... main()

2021/12,江端さんの技術メモ

お題: subPerson1が終了したら subPerson2も巻き添えで強制的に終了させるには?
当初、一方が終了したら、他方も終了するように作りたかったのだけど、いいやり方が思いつかなかったので、subPerson1 → subPerson2 の順番で終わせるような実装にした。
まあ、subPerson1を送信専用、subPerson2を受信専用のgoroutineとすれば、まあ、いけるんじゃないかな、と
/*
	お題: subPerson1が終了したら subPerson2も巻き添えで強制的に終了させるには?
	当初、一方が終了したら、他方も終了するように作りたかったのだけど、分からなかったので、subPerson1 → subPerson2 の順番で終わせるような実装にした
*/

package main

import (
	"fmt"
	"sync"
	"time"
)

func subPerson1(i int, wg *sync.WaitGroup, ch chan struct{}) {
	defer wg.Done()
	time.Sleep(1 * time.Second)
	fmt.Println("		End of sub_person1(", i, ")")
	close(ch) // subPerson2に終了を通知する
}

func subPerson2(i int, wg *sync.WaitGroup, ch chan struct{}) {
	defer wg.Done()
	<-ch // subPerson1 のclose(ch)が発行されるまでロック (普通はselect待ちにする)
	fmt.Println("		End of sub_person2(", i, ")")
}

func person(i int, wg *sync.WaitGroup) {
	fmt.Println("	Start... person(", i, ")")
	defer wg.Done()

	subWG := sync.WaitGroup{}

	subWG.Add(2)
	ch := make(chan struct{})
	go subPerson1(i, &subWG, ch)
	go subPerson2(i, &subWG, ch)

	subWG.Wait()

	fmt.Println("	End... person(", i, ")")
}

func main() {
	fmt.Println("start... main()")
	wg := sync.WaitGroup{}
	for i := 0; i < 5; i++ {
		wg.Add(1) // goルーチンを実行する関数分だけAddする

		go person(i, &wg)
	}

	wg.Wait()
	fmt.Println("end of ... main()")
}
出力結果
ebata@DESKTOP-P6KREM0 MINGW64 ~/goga/0-2
$ go run main.go
start... main()
        Start... person( 4 )
        Start... person( 0 )
        Start... person( 1 )
        Start... person( 3 )
        Start... person( 2 )
                End of sub_person1( 3 )
                End of sub_person2( 3 )
        End... person( 3 )
                End of sub_person1( 0 )
                End of sub_person1( 4 )
                End of sub_person2( 4 )
        End... person( 4 )
                End of sub_person2( 0 )
        End... person( 0 )
                End of sub_person1( 1 )
                End of sub_person2( 1 )
        End... person( 1 )
                End of sub_person1( 2 )
                End of sub_person2( 2 )
        End... person( 2 )
end of ... main()

とまあこんな感じで、sub_person1 → sub_person2 → person という順番でgoroutineが終了していることが確認できました。

2021/12,江端さんの技術メモ

先程、情報開示請求先の、総務省の担当者の方から、『本日中に資料を送付して頂ける』旨の電話連絡を頂きました。

総務省の方からお電話頂き、調べ方について丁寧に御説明頂きました。まずは手順を忘れない内にメモを残しておきます。(政治資金収支報告書のオンライン提出を怠っている政治団体を全部開示する件 続報)

I received a phone call from the person in charge at the Ministry of Internal Affairs and Communications, to whom I made a request for information disclosure, stating that they would be able to send me the documents today.

そもそも、存在していなかった資料をわざわざ作って頂いているので、時間がかかるのは覚悟しているたのですが ――

I was prepared for it to take a long time, since they had to create a document that didn't exist in the first place, however...

それにしても、丁寧なフォローをして頂いて、恐縮してしまいます。

Nevertheless, I'm very grateful for their careful follow-up.

-----

親切が嬉しい反面、ちょっと心配になってきました。

While I'm glad for their kindness, I'm getting a little worried.

この対応の理由には、3つのケースが考えられると思うからです。

The reason for this response is that I think there are three possible cases.

(1)基本的に総務省の担当者の方が親切

(1) Basically, the person in charge at the Ministry of Internal Affairs and Communications is kind.

(2)情報開示請求をしてくるような民間人はやっかな奴が多い → その対応のノウハウがある

(2) Many private citizens who request disclosure of information are difficult, so they have the know-how to deal with them.

(3)こんなコラムを書いているような奴(江端)を怒らせると面倒

(3) A guy who writes a column like this (Ebata) can be a pain in the ass if they piss him off.

上記の(1)だといいけど、(3)だとちょっと悲しいなぁ、と思っています。

I hope it's (1) above, but if it's (3), I'm a little sad.

-----

あ、第4のケースもありそうです。

Oh, there may be the fourth case.

(4)「政治資金収支報告書のオンライン提出を怠っている政治団体」を、江端から思いっきりDisって欲しい

(4) They want Ebata to disrespect "political organizations that fail to submit their political fund balance reports online" with all his might.

うん、これありそうだな。

Yeah, that's a possibility.

『政府としては、政治団体に恥をかかせるのはマズいけど、民間人のライター(江端)がやってくれるなら、それに越したことはない』

"It's not good for the government to embarrass a political group, but if a civilian writer (Ebata) can do it, so much the better"

と。

これなら、政府と私が、Win-Winです。

This is a win-win situation for the government and me.

-----

まあ、こんな感じで、『アナログ かつ アナクロ な政治団体を見張っていくのは、私のようなシニアの義務だろう』てなことを思っています。

In this way, I think it is the duty of senior citizens like me to keep an eye on analog and analogous political organizations.

2021/12,江端さんの技術メモ

C/C++では、構造体を丸ごと送信するのに、文字列にキャストを被せて無理矢理送り込むということをやっていました。

Goの場合、チャネルに ch chan interface{}を使うと、何でも運んでくれるようなので、これで同じように「手を抜く」を考えていました。

で、色々試した結果、こういう風に使えるらしいので自分用のメモとして残しておきます

// 単一通信の構造体
type SingleCaster struct {
	//ch   chan int   // 単一通信路
	ch   chan interface{}
	lock sync.Mutex // 単一通信路のロック
}

でもって、

type locInfo struct {
	lon float64
	lat float64
}
でもって、
type PERSON struct {
    number      int     // 人間番号
    live        bool    // 存在フラグ 存在:true 消滅:false
    destination locInfo // 出発座標
    arrival     locInfo // 到着座標
    distance    float64 // 到着座標と出発座標の距離
    present     locInfo // 現在位置
}

を、こんな風に運びたい時、

sc_person.ch <- person.present

これで、元に戻ります。

case v_p := <-sc_person.ch:
			fmt.Println("catched from person send", v_p)
			//var ll locInfo
			ll := v_p.(locInfo)
			fmt.Println(ll.lon, ll.lat)

channelで構造体を送り込む方法

var ch1 chan interface{}

type PERSON struct {
	number      int     // 人間番号
	action      int     // 0:リクエスト 1:乗車 2:降車
}

func sub1(){
	 var person PERSON
	 person.number = 1
	 person.action= 2

	 ch1 <- person 
} 

func sub2(){

	 p := <-ch1

	 person := p.(PERSON)
	 fmt.Println(person) 
}

2021/11,江端さんの技術メモ

  • Go言語のコーディングしている最中に、バグを指摘してくる(お前はツンデレ彼女か)
  • 適当なメソッドを書き込むと、自動的にimport関数を付け加えてくるところ(お前はお袋か)
  • バグではないけど、不効率なコーディングをしていると、もっと良いやり方を提案してくる(お前は構いたがりのメンターか)

―― なんか、ちょっと怖い