2020/10,江端さんの忘備録

我が国では、「非婚者」の比率が増えてきています。

The proportion of "non-married" people is increasing in our country.

『「非婚」という選択が幸せである』というのではなく、事実『「非婚」は幸せである』のです。

It's not that 'choosing to be 'non-married' is a happy choice,' but the fact that 'non-marriage' is a happy choice.

そもそも「他人と共に生きる」という人生は、それ自体がハードルの高い生き方です。

To begin with, a life of "living with others" is a hurdle in itself.

自分の管理・制御下にない人間と、(大抵の場合は)生涯パートナーとして生きていくというのは、それ自体が奇跡である、と ―― そういう当たり前のことに、ようやく人類は気がつき出したのだと思います。

"living as a partner who is not under our management and control is a miracle (in most case)". I think we are finally realizing that this is a matter of course.

-----

「非婚」によって、出生率が低下し、生産力が減り、国力が削られる ―― なるほど、そうかもしれません。

"Non-marriage" reduces the birth rate, reduces the productive capacity, and diminishes the nation's strength -- okay, maybe so.

―― だったら、何だというのだ?

"What's the matter, even if so ?"

国民の選択によって、国家が衰退するなら、それは国家の運命です。

If a nation is decimated by the choices of its people, it is the fate of the nation.

少なくとも私は構いません ―― 衰退していく国家であっても、それに適応しながら、なんとか生きていける程度には、私は、毎日、勉強し続けています。

At least I don't mind. I continue to learn, every day, to manage to live with it, even in a declining nation, while adapting to it.

-----

どうも、勘違いしている人が多いようですが、「国家(特に政府)は、国民に対して役務(サービス)を提供する主体」です。

Apparently, there are a lot of people who are mistaken. "The state (especially the government) is an entity that provides services to its citizens".

「国民が、国家に使役する義務は1mmもない」のです。

The people are under no obligation to serve the state at all.

なぜ少子化対策をしているのか? ―― これも勘違いしている人が多いようです。

Why is the government taking measures against the declining birthrate? It seems that many people misunderstand this as well.

少子化対策をしているのは、現状の日本国というシステムが必要とする人数を、維持したいからです。

The reason why the government is taking measures against the declining birthrate is because the government wants to maintain the number of people that the current system of Japan needs.

その為には、人口を維持する戦略「少子化対策」が、一番コストが安いからです。

For that purpose, the strategy to maintain the population, "Countermeasures against the declining birthrate," is the cheapest.

-----

しかし、少子化は、もう避けられません。

However, the declining birthrate is inevitable.

少子化が避けられないのであれば、少子化に適応させる方向で、日本国というシステムを変更(縮退)させるしかありません。

If the declining birthrate is unavoidable, there is no choice but to change (degenerate) the system of Japan in the direction of adapting to the declining birthrate.

もっとも、そのようなシステム変更が「簡単である」とは言いませんが、少子化は文明と歴史の必然です。

Although I do not say that such system changes are "easy", the declining birthrate is an inevitable part of civilization and history.

面倒くさらがずに「現状のシステムを変更」し、必要であれば「現状のシステムを放棄する」覚悟が必要とされています。

We need to be prepared to "change the current system" and, if necessary, "abandon the current system" without any hassle.

(まあ、テクノロジーによる解決法もあるのですが、今回は割愛します)

(Well, there is a technology solution, but I'll omit it this time.)

-----

ただ ―― 「非婚」を選んだ人たちに、申し上げたいことはあります。

However, I would like to call attention to those who chose "unmarried."

「非婚」を選んだ人が、頻繁に親戚などの家庭を訊ねる、という傾向が散見されます。

There is a tendency for people who choose "unmarried" to frequently ask their relatives' families.

『休日になると、親戚のその家にいりびたり、子どもたちと遊んで、一日過ごしていく』ということを、日常的に行っている者がいます。

Some people regularly do "on holidays, spend the day at their relatives' homes, playing with their children,".

はっきり言いますが ―― 鬱陶(うっと)しい

To be clear, they are annoying.

というか、空気読め、バカ。

In other words, "Read the atmosphere. this idiot!"

「非婚」を選択しておきながら、何、ラクして「アットホーム」だけを享受しようとしているんだ。

Why you are trying to enjoy only "at home" with ease, even you have selected "unmarried".

厚かましいにも程がある。

You have quite a nerve.

「非婚」という「自由」を選択したのであれば、それに付随する「孤独」も一緒に飲み込め。

If you've chosen the "freedom" of "non-marriage," then swallow the "loneliness" that comes with it, too.

それがトレードオフというものだ。

That's called a trade-off.

例えば、幼児や小学生の女児がいるような家に、頻繁に独身の男がやってくるのを、歓迎する親がいると思うか?

For example -- do you think any parent would welcome a single man who frequents a house with toddlers and school-age girls?

はっきり言って「気持ち悪い」し、もっとはっきり言えば「怖い」。

To be clear, it is "unpleasant", and more clearly, it is "scary".

そもそも『いい歳こいて、自分一人で、自分自身を楽しませる方法すら確立できない奴』というだけで、信用は絶無だ。

In the first place, if you're 'a good old man, on your own, who can't even establish how to entertain himself,' you have no credibility.

―― ということを、本人の前でハッキリと言うのは難しいのです(私は例外)。

It's hard to say that clearly in front of you (I'm an exception).

-----

ともあれ『非婚者の訪問は、既婚者の家庭では歓迎されていません』。察して下さい。

Anyway, 'visits from non-married people are not welcome in the homes of married people'. Please guess.

『「非婚」という選択が幸せである』を選んだ人は、生涯、それを、たった一人で貫ぬく覚悟と義務があります。

Those who choose "Non-marriage is a happy choice" have a lifelong obligation to carry it out alone.

厚かましくも、人様が苦労して作り上げた「幸せシステム」に「ただ乗り」するような奴は ―― 少なくとも、私は許しません。

I won't tolerate anyone who "free rides" on the "happiness system" that others have worked so hard to create.

2020/10,江端さんの忘備録

(昨日の続きです)

(Continuation from yesterday)

しかし、私の娘たちは、父親の「技術力」や「資質」を使い倒すことに対しては、一切の躊躇がありません。

However, my daughters have no hesitation about using their father's "technical skills" and "qualities" to defeat him.

家電機器の設定、ネットワーク配線、パソコンの初期構築、ソフトウェアのインストールから、学術レポート書き方、英語翻訳、工作加工、就職や入学試験対応、プレゼンテーション資料の作り方や纏め方 ―― 果ては、

How to set up appliances, network wiring, initial computer setup, software installation, academic report writing, English translation, crafting, job and school entrance exams, how to make and organize presentation materials -- and more,

「自分」の志望動機や、「自分」の将来の夢、に至るまで、「この私」にネタ出し(ブレーンストーミング)をさせます。

They let "me" brainstorm about everything from their motivations for applying for jobs to their dreams for the future.

その為であれば、暗に父親の就寝時間まで指定してきます(例: 『パパさぁ、今日、午前4時より前に寝ちゃう?』)

They will even implicitly specify a bedtime for their father (e.g., "Dad, are you going to bed before 4:00 a.m. today?").

-----

江端:『あのなぁ、なんで、私がお前たちの"動機"や"夢"まで考えなければならないのだ?』

Ebata: "Listen, why do I have to think about your 'motives' and 'dreams' as well?

娘:『いや、私がパパに期待しているのは、"動機"や"夢"に繋げるまでの、論理的な筋道(説明)だよ』

Daughter: "No, what I expect you is a logical path (explanation) to connect to my 'motives' and 'dreams'"

そう。その通り。

Exactly.

"動機"や"夢"を語ることは、それほど難しくありません(もちろん「難しい」という人も沢山いますが)。

"It's not that difficult to talk about their "motivation" and "dreams" (although of course there are many people who say it's difficult).

本当に難しいのは、その"動機"や"夢"に至るまでの、具体的な事例と、客観的な実現性と、そこそこ迫力とドラマのあるストーリー作りです。

What is really difficult is to create a story with concrete examples, objective feasibility, and moderate power and drama, to lead up to the "motivation" and "dream".

-----

実は、これ、特許明細書の書き方と同じです。

In fact, this is the same as how to write a patent specification.

特許明細書は、国家に対して、発明の独占的使用権の付与を請求するための、行政書類です。

A patent specification is an administrative document for requesting the state to grant an exclusive right to use an invention.

しかし、その書類の中には、審査官を納得させ、そこそこ感動させる力強いストーリーも必要なのです。

However, some of the documents also need a powerful story that convinces and impresses the examiner.

それ故、発明を生業(なりわい)とするエンジニアには、「技術力」に加えて、「ストーリーテーラー」としての資質も要求されるです。

Therefore, an engineer whose business is invention is required not only to have "technical ability" but also to have qualities as a "storyteller".

-----

総じて、私は ―― 『娘にブランドバッグをねだられる方が、ラクだな』と思える程度には、娘たちに、コキ使われています。

In general, my daughters have used me as a convenience, like 'it is easier to beg my daughter for a branded bag'

2020/10,江端さんの忘備録

子どもの頃の私は、「親に宿題を手伝って貰う」という考え方がありませんでした。

As a child, I didn't have a "get my parents to help me with my homework" mentality.

―― ジョーダンではない!そんなみっともないことができるか!

"No kidding! I can't be so disgusting!"

が、私の考え方の中心でした。

It was the center of my thinking.

学費とか生活必需品とかの例外を除き、「親にお金をねだる」ということをやったこともありません。

I've never done the "begging my parents for money" thing, with the exception of school fees or other necessities.

というか――「できなかった」。

I mean - "I couldn't".

我が家は、決して裕福な家庭ではなかったですし、父も母も、下町の木工会社を経営しながら、真の意味において「命懸け」で働いているのを、(私も、時々、その手伝いをしながら)見てきたからです。

My family was not a wealthy one, and I watched (and sometimes helped) my father and mother run a downtown woodworking company, working for their "lives" in the true sense of the word.

# 本当に、父も母も、何度か死にかけて、入院(ICU等を含む)をしていました。

# Really, both my father and mother was about to die several times and were hospitalized (including ICU etc.).

-----

一方、嫁さんの方は、当たり前の様に、義父や義母に宿題を手伝って貰っていたそうです。

My wife, on the other hand, had her father-in-law and mother-in-law help her with her homework, as was the norm.

「プライド」とかの問題より「ラクできるなら何だって使う」という一貫したポリシーがあり、そこに「後ろめたさ」は、全くなかったそうです。

She had a consistent policy of "use whatever it takes to make it easier" rather than "her pride," and she never felt guilty about it.

もはや、これは、「是非の問題」ではなく「文化の相違」としか言いようがありません。

This is no longer a "right or wrong" thing to say, but rather a cultural difference.

それはさておき。

Aside from that.

-----

先日、娘から、

The other day, my daughter told me

―― 自分の娘に『何か欲しいものはないか?』と訊ねて、娘に買い与える父親がいる

"The father of her friend asks his daughter, "Do you have anything you want? and buys it for his daughter"

と聞きました。

その瞬間、私は『気持ち悪!』と思いました。

At that moment, I thought, "It feels bad!"

江端家では、そのような光景が出現したことはありませんし、これからもないでしょう。

Such a scene has never appeared in the Ebata family, and it will never happen.

娘に「訊ねて」まで買い与える金があれば、私は私の欲しいものを買います ―― 技術書とか、装置とか、ソフトウェアとか、各種のデータ資料とか。

If I have the money to buy my daughter until I "ask" her, I will buy what I want -- technical books, equipment, software, various data materials, and so on.

娘には『自分の欲しいものは、自分で手に入れろ』と言い聞かせてありますので、娘も、私に無駄なことはしてきません。

I've told my daughters, 'You get what you want by yourself' so they won't waste their time on me, either.

(続く)

(To be continued)

2020/10,江端さんの忘備録

現在、想定100ページを越えるであろう、報告書の作成をしています。

I am currently working on a report, which is expected to be in excess of 100 pages.

資料のネタは十分にあり、これを構成しなおせば報告書として完成するのですが、なかなかに長丁場のしんどい作業になりそうです。

I have enough material, and if I re-structure it, it will be completed as a report, but it's going to be a long and tedious process.

昔は、このような作業は、音楽やアニメを見ながらでも作業できたのですが、最近、これができなくなっています。

In the past, I used to be able to work on these tasks while watching music or cartoons, but lately this has been impossible.

2つの作業を同時にできなくなってきています。

I come to be able to do both tasks at the same time.

これは私の脳の並列処理能力(マルチタスク)が、壊れつつあることの証拠だと思います。

I think this is evidence that my brain's parallel processing capacity (multitasking) is breaking down.

-----

ですが、すでに、視聴済みのコンテンツであれば、マルチタスクができる場合があります。

But you may be able to multitask with content you've already watched.

私の場合、「三国志 three kingdoms」が、これに該当します。

In my case, "Three Kingdoms" is it.

もう、すでに、このコンテンツ自体が、私にとってのイージーリスニングの部類に入っています。

Already, this content itself is already in the easy listening category for me.

まあ、そういう訳で、全部合わせて95話、約100時間のドラマを、ダラダラと聞きながら仕事をしています。

All in all, I work through 95 episodes, about 100 hours of drama, while lazily listening to it.

-----

で、まあ、時々、仕事の合間にボンヤリと考えるのですが

And, well, sometimes I think about this drama.

―― 諸葛孔明が何度も試みた「北伐」って、要するに「侵略戦争」だよなぁ

"The 'northern expedition' that Zhuge Liang tried many times is, in short, an 'aggression war'"

とか、

and

―― 落鳳坡で 劉備のフリををしたホウ統(士元)が、計算の上で命を落とすのは覚悟の上だろうけど、その部下は、訳も分からず巻き添え喰らって殺されたんだよなぁ

I'm sure that Hou Tong (Shi Yuan), who pretended to be Liu Bei at "Rakuhouha", was prepared to lose his life in his calculation, but that subordinate would have been killed by collateral damage for no reason.

とか、

三国志の名シーンを「台無し」にするような感想を浮かべながら、仕事を続けています。

I continue to work with thoughts that "ruin" famous scenes from the Three Kingdoms.

2020/10,江端さんの忘備録

よくアニメやドラマで登場する「教師」などを見て、

Looking at a "ideal teachers" in cartoons and dramas.

『あんな先生が、学校にいてくれたらなー』

"I wish I had a teacher like that at school"

とか、

or

『そんな先生と巡りあっていたら、私の人生も違っていただろうに』

"My life would have been different if I'd had a teacher like that"

という書き込みが散見されます。

I can read scattering of posts like the above on the Internet.

ちょっと調べてみたら、そういうページが沢山ありました。

I did a little research and found a lot of those pages.

ちょっと前なら、「暗殺教室」の「殺せんせー」、最近なら、「俺の青春ラブコメは間違っている」の「平塚先生」などなど。

Not so long ago, it would have been "Koro-Sensei" in "Assassination Classroom", and more recently, it would have been "Hiratsuka-sensei" in "My youth romantic comedy is wront as I expected".

-----

一方

The other side,

『将来、あんな先生になるんだ』

"I'm gonna be that teacher one day"

とか、

or

『私は、今、あんな風に子どもを助ける大人として、がんばっている』

"I'm trying my best to be an adult who helps kids like that now"

という書き込みは、

I could not find the phrases like the above

―― たったの一つも

"at all"

見付けることはできませんでした。

-----

結論:

Conclusion:

私達は、

We are creatures that

■自分の為に、他人に理想を押しつけ、

impose our ideals on others for your own sake,

■他人の為には、自分に努力を課さない、

don't work hard for others.

そういう生き物です。

2020/10,江端さんの忘備録

人間は、他人を他人として認識するのではなく、その他人の属する所属や地位、環境を含めて認識します。

Humans don't perceive others as others but others including their affiliations, status, and environments.

「部長の山田さん」「新人の田中さん」「技術者の佐藤さん」「ドイツ在住の高橋さん」等々です、

Mr. Yamada, the department head, Ms. Tanaka, the new guy, Mr. Sato, the technician, Ms. Takahashi, who lives in Germany, and so on.

特に初対面の場合は、そうなるのは仕方がありません。

Especially in the case of the first meeting, it can not be helped.

その時の私たちは、他人を評価する情報を全く持っていないからです。

At that time, we have no information to evaluate others.

-----

ただ、「名物研究員の江端さん」というフレーズには、所属、地位、環境を含んでいません。

However, the phrase "Mr. Ebata, a famous researcher" does not include affiliation, position, or environment.

そこには、敬意とも蔑視とも解釈可能な「形容句」が入っているだけです。

It only contains "adjectives" that can be interpreted as both respect and contempt.

先日も、メールの中にこのフレーズを見つけて、『なるほど、私は"名物研究員"なんだ』と認識しました。

The other day, I found this phrase in an email and realized that "I see, I'm a famous researcher".

-----

「こちらが、同じ部署の江端です」という同僚の紹介で、先方の方と名刺交換をしている時に、

When I was exchanging business cards with the other person, I was introduced by a colleague who said, "This is Ebata from the same department."

『ああ、こちらが、あの江端さん・・・、お噂はかねがね伺っております』

"Oh, You are Mr. Ebata... I've heard a lot of great things about you."

というコメントを頂きました。

I got the comment.

-----

―― "ソースは誰?"

"Who is the source ?"

―― "どんな噂?"

"What kind of great things ?"

と、突っ込みたくなっても、苦笑いしながら、それを、グっと我慢するのが、

Even if I want to dig in, I have to put up with it with a bitter smile.

「大人の社会人」というものです。

This is an "adult business people"

2020/10,江端さんの技術メモ

木材から円形(円盤)を切り出すことが必要となり、色々試しています。

このような、電動ドライバーに装着できる、木材用の円切りサークルカッターを使っていました。

しかし、これで作業すると、直径20cmの円を切り出すのに、(慣れてきても)10分以上はかかるので、非常に効率が悪く、恐しく疲労します。

そこで、今回、BOSCH(ボッシュ)の電動ノコギリを使って木板を円形に切ることのできる、BOSCHのジグソー円曲平行ガイドを購入しました(別の会社の電動ノコギリの場合、その会社が提供しているものを購入する方が安全です)

先程、自宅に届いたので、さっそく、自分のメモとしてジグソー円曲平行ガイドを、袋から取り出すところから、切り出すまでの全行程を撮影しました。

 

映像の中では、キレイな円形の切出しに失敗していますが、これは中心線をズラさないようにすれば、必ず成功しますので御安心下さい。

サークルカッターと比較して、もの凄くラクチンに円盤を切り出せました。

電動ノコギリとジグソー円曲平行ガイドを接合した状態の写真↓

接合部分の拡大写真↓

以上

未分類

このコンテンツはパスワードで保護されています。閲覧するには以下にパスワードを入力してください。

2020/10,江端さんの技術メモ

スマホから位置情報を取得するところまできたが、https(wss)対応にしないと位置情報が取り出せないようです(かなりしつこく聞いていましたが、すっかり忘れていました)。

で、今のGolangのサーバプログラムをhttps対応にすべく、色々試したのですが、なんかこれで動いているようなので、要点だけ記載します。

Step.1 

まず、

C:\Users\ebata\WssSample\goClient>go run goClient.go conn.go hub.go tls: first record does not look like a TLS handshake がなんともならない件

の、mkcertを使って生成した鍵(“algo.key"と"algo.crt")をディレクトリに放り込む

Step.2

serverXX.goの、サーバ作成部を以下のように変更する

/*
		log.Fatal(http.ListenAndServe(*addr, nil)) // localhost:8080で起動をセット
	*/

	var httpErr error
	if _, err := os.Stat("./algo.crt"); err == nil {
		fmt.Println("file ", "algo.crt found switching to https")
		if httpErr = http.ListenAndServeTLS(*addr, "algo.crt", "algo.key", nil); httpErr != nil {
			log.Fatal("The process exited with https error: ", httpErr.Error())
		}
	} else {
		httpErr = http.ListenAndServe(*addr, nil)
		if httpErr != nil {
			log.Fatal("The process exited with http error: ", httpErr.Error())
		}
	}

Step.3

htmlファイルの、"http://"を、片っ端から"https://"に書き換える。

さくっと動いて気持ち悪いのですけど、まあ動くのであれば、なんでも良いです。

 

2020/10,江端さんの技術メモ

スマホから使えるようにした(今は、ランダムウォークだけ)。

/*
// server22.go ペアはclient9.go

// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ignore

// 使い方
// go run server13.go      (適当なシェルから)
// http://localhost:8080  (ブラウザ起動)
// http://localhost:8080/smartphone (スマホ起動)
*/

package main

import (
	"flag"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"sync"

	"github.com/gorilla/websocket"
)

// GetLoc GetLoc
type GetLoc struct {
	ID  int     `json:"id"`
	Lat float64 `json:"lat"`
	Lng float64 `json:"lng"`
	//Address string  `json:"address"`
}

//var addr = flag.String("addr", "localhost:8080", "http service address")
var addr = flag.String("addr", "0.0.0.0:8080", "http service address") // テスト

var upgrader = websocket.Upgrader{} // use default options

var chan2_1 = make(chan GetLoc)

var maxid = 0

var mutex sync.Mutex

func echo2(w http.ResponseWriter, r *http.Request) {
	c, err := upgrader.Upgrade(w, r, nil) // cはサーバのコネクション
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer c.Close()

	//mutex := new(sync.Mutex)

	for {
		//mt, message, err := c.ReadMessage() // クライアントからのメッセージの受信(mtはクライアント識別子)
		//_, _, err := c.ReadMessage() // クライアントからのメッセージの受信(mtはクライアント識別子)

		//mutex.Lock()  // ここに置くとデッドロックしてしまう

		gl := new(GetLoc)

		err := c.ReadJSON(&gl) // クライアントからのメッセージの受信

		mutex.Lock()

		// 原因不明の対処処理
		if gl.ID == 0 && gl.Lat < 0.01 && gl.Lng < 0.01 {
			mutex.Unlock()
			break
		} else if gl.ID < -1 { // 受理できないメッセージとして返信する
			//条件分岐 (変なIDが付与されているメッセージは潰す)
			//if (gl.ID > maxid) || (gl.ID < -1) { // 受理できないメッセージとして返信する

			gl.ID = -1
			gl.Lat = -999
			gl.Lng = -999
			err2 := c.WriteJSON(gl)
			if err2 != nil {
				log.Println("write1:", err2)
				mutex.Unlock()
				break
			}
		} else { // それ以外は転送する
			log.Printf("echo2 after c.WriteJSON(gl) ID:%d", gl.ID)
			log.Printf("echo2 after c.WriteJSON(gl) Lat:%f", gl.Lat)
			log.Printf("echo2 after c.WriteJSON(gl) Lng:%f", gl.Lng)

			if err != nil {
				log.Println("read:", err)
				mutex.Unlock()
				break
			}
			fmt.Printf("echo2 before chan2_1 <- *gl\n")
			chan2_1 <- *gl
			fmt.Printf("echo2 after chan2_1 <- *gl\n")

			//で、ここで受けとる
			//gl2 := new(GetLoc)
			fmt.Printf("echo2 before gl2 := <-chan2_1\n")
			gl2 := <-chan2_1
			maxid = gl2.ID // ID最大値の更新
			log.Printf("echo2 after gl2 := <-chan2_1 ID:%d", gl2.ID)
			log.Printf("echo2 after gl2 := <-chan2_1 Lat:%f", gl2.Lat)
			log.Printf("echo2 after gl2 := <-chan2_1 Lng:%f", gl2.Lng)

			fmt.Printf("echo2 before err2 := c.WriteJSON(gl2)\n")
			err2 := c.WriteJSON(gl2)
			fmt.Printf("echo2 after err2 := c.WriteJSON(gl2)\n")
			if err2 != nil {
				log.Println("write2:", err2)
				mutex.Unlock()
				break
			}
			fmt.Printf("end of echo2\n")

		}

		mutex.Unlock()
	}
}

func echo(w http.ResponseWriter, r *http.Request) {

	c, err := upgrader.Upgrade(w, r, nil) // cはサーバのコネクション
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer c.Close()

	/*	ここでロックして待つ */

	for {

		fmt.Printf("echo before gl := <-chan2_1\n")
		gl := <-chan2_1
		fmt.Printf("echo after gl := <-chan2_1\n")

		fmt.Printf("echo before err = c.WriteJSON(gl) gl2.id = %d\n", gl.ID)
		fmt.Printf("echo before err = c.WriteJSON(gl) gl2.lat = %f\n", gl.Lat)
		fmt.Printf("echo before err = c.WriteJSON(gl) gl2.lng= %f\n", gl.Lng)
		err = c.WriteJSON(gl)
		if err != nil {
			log.Println("WriteJSON1:", err)
		}
		fmt.Printf("echo after err = c.WriteJSON(gl)\n")

		fmt.Printf("echo before err = c.RreadJSON(gl)\n")
		gl2 := new(GetLoc)
		err2 := c.ReadJSON(&gl2)
		fmt.Printf("echo after err = c.ReadJSON(&gl2) gl2.id = %d\n", gl2.ID)
		fmt.Printf("echo after err = c.ReadJSON(&gl2) gl2.lat = %f\n", gl2.Lat)
		fmt.Printf("echo after err = c.ReadJSON(&gl2) gl2.lng= %f\n", gl2.Lng)
		if err2 != nil {
			log.Println("ReadJSON:", err2)
		}
		// ここからチャネルで返す
		fmt.Printf("echo before chan2_1 <- *gl2 gl2.id = %d\n", gl2.ID)
		fmt.Printf("echo before chan2_1 <- *gl2 gl2.lat = %f\n", gl2.Lat)
		fmt.Printf("echo before chan2_1 <- *gl2 gl2.lng = %f\n", gl2.Lng)
		chan2_1 <- *gl2
		fmt.Printf("echo after chan2_1 <- *gl2\n")
		fmt.Printf("end of echo\n")
	}

}

func home(w http.ResponseWriter, r *http.Request) {
	homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
}

func smartphone(w http.ResponseWriter, r *http.Request) {
	smartphoneTemplate.Execute(w, "ws://"+r.Host+"/echo2")
}

func main() {
	flag.Parse()
	log.SetFlags(0)

	http.HandleFunc("/echo2", echo2)           // echo関数を登録 (サーバとして必要)
	http.HandleFunc("/echo", echo)             // echo関数を登録 (サーバとして必要)
	http.HandleFunc("/", home)                 // home関数を登録
	http.HandleFunc("/smartphone", smartphone) // smartphone関数を登録
	log.Fatal(http.ListenAndServe(*addr, nil)) // localhost:8080で起動をセット
}

var smartphoneTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script> 

function obj(id, lat, lng){
	this.id = id;
	this.lat = lat;
	this.lng = lng;
}

function random(min, max){
	return  Math.random()*(max-min) + min;
}

// var personal_id;

var lat = 35.654543;
var lng = 139.795534;  

window.addEventListener("load", function(evt) {
    var output = document.getElementById("output");
    var input = document.getElementById("input");
    var ws;
    var print = function(message) {
        var d = document.createElement("div");
        d.textContent = message;
        output.appendChild(d);
	};

	var personal_id = 0;

	
	///// 起動時のボタン
	// disabled属性を削除
	document.getElementById("open").removeAttribute("disabled");
	document.getElementById("open").style.color = "black";

	// disabled属性を設定 (closeボタンを非活性化)
	document.getElementById("close").setAttribute("disabled", true);
	document.getElementById("close").style.color = "White";	

	// disabled属性を設定 (sendボタンを非活性化)
	document.getElementById("send").setAttribute("disabled", true);
	document.getElementById("send").style.color = "White";	


		
	document.getElementById("open").onclick = function(evt) {
		console.log("document.getElementById open");

		// disabled属性を設定 (openボタンを非活性化)
		document.getElementById("open").setAttribute("disabled", true);
		document.getElementById("open").style.color = "White";		

		// disabled属性を削除
		document.getElementById("send").removeAttribute("disabled");
		document.getElementById("send").style.color = "black";	

		// disabled属性を削除
		document.getElementById("close").removeAttribute("disabled");
		document.getElementById("close").style.color = "black";	

		////////// 削除2
		// ws = new WebSocket("{{.}}");
		////////// 削除2終り


		////////// 削除1
		//var send_obj = new obj(0, 35.654543,139.795534);  // 最初は"0"でエントリ

		//console.log("open:send_obj");	
		//console.log(send_obj.id);	
		//console.log(send_obj.lat);
		//console.log(send_obj.lng);		

		//var json_obj = JSON.stringify(send_obj);
		//ws.send(json_obj);
		/////////// 削除1終り


        if (ws) {
            return false;
        }
		
		
		////////// 追加2
		ws = new WebSocket("{{.}}");
		////////// 追加2終り

		
        ws.onopen = function(evt) {
			print("OPEN");
		
			//ws = new WebSocket("{{.}}");
			
			////////// 追加1			
			var send_obj = new obj(0, 35.654543,139.795534);  // 最初は"0"でエントリ

			console.log("open:send_obj");	
			console.log(send_obj.id);	
			console.log(send_obj.lat);
			console.log(send_obj.lng);		

			var json_obj = JSON.stringify(send_obj);
			ws.send(json_obj);
			/////////// 追加1終り

		}
		
        ws.onclose = function(evt) {

			print("CLOSE");
            ws = null;
        }

		ws.onmessage = function(evt) {  // 受信したメッセージはここに飛んでくる
			print("RESPONSE: " + evt.data);  // jsonメッセージの内容を表示
			// データをJSON形式に変更
			var obj = JSON.parse(evt.data);

			personal_id = obj.id; // IDの取得(何回も取る必要はないが)
			console.log("personal_id");			
			console.log(personal_id);

			
			if ((Math.abs(obj.lat) > 90.0) || (Math.abs(obj.lng) > 180.0)){ // 異常な座標が入った場合は、マーカーを消去する
				console.log("before ws.close()");
				ws.close();
				console.log("after ws.close()");
			}
		}
		
        ws.onerror = function(evt) {
            print("ERROR: " + evt.data);
        }
        return false;
    };
	
	document.getElementById("send").onclick = function(evt) {

		console.log("document.getElementById send");

		// disabled属性を設定 (openボタンを非活性化)
		document.getElementById("open").setAttribute("disabled", true);
		document.getElementById("open").style.color = "White";	
	
		// disabled属性を削除
		document.getElementById("send").removeAttribute("disabled");
		document.getElementById("send").style.color = "black";	

		// disabled属性を削除
		document.getElementById("close").removeAttribute("disabled");
		document.getElementById("close").style.color = "black";	
	
		if (!ws) {
			console.log("return false send");
			return false;			
		}

		lat += random(0.5, -0.5) * 0.00001 * 10 * 5;
		lng += random(0.5, -0.5) * 0.00002 * 10 * 5

		
		//var send_obj = new obj(personal_id, 35.654543,139.795534);  // idでエントリ
		var send_obj = new obj(personal_id, lat, lng);  // idでエントリ

		console.log("send:send_obj");	
		console.log(send_obj.id);	
		console.log(send_obj.lat);
		console.log(send_obj.lng);		

		var json_obj = JSON.stringify(send_obj);
		ws.send(json_obj);		

		/*
        print("SEND: " + input.value);
        ws.send(input.value);
		return false;
		*/

		return false;	
    };

	document.getElementById("close").onclick = function(evt) {
		console.log(" document.getElementById close");

		// disabled属性を削除
		document.getElementById("open").removeAttribute("disabled");
		document.getElementById("open").style.color = "black";

		// disabled属性を設定 (closeボタンを非活性化)
		document.getElementById("close").setAttribute("disabled", true);
		document.getElementById("close").style.color = "White";	

		// disabled属性を設定 (sendボタンを非活性化)
		document.getElementById("send").setAttribute("disabled", true);
		document.getElementById("send").style.color = "White";			


        if (!ws) {
            return false;
		}
	
		var send_obj = new obj(personal_id, 999.9, 999.9);  // 最初は"0"でエントリ

		console.log("close:send_obj");
		console.log(send_obj.id);		
		console.log(send_obj.lat);
		console.log(send_obj.lng);		

		var json_obj = JSON.stringify(send_obj);
		ws.send(json_obj);

        //ws.close();  // これはws.onmessageの方で実施
        return false;
    };
});
</script>
</head>
<body>
<table>
<tr><td valign="top" width="50%">
<p>Click "Open" to create a connection to the server, 
"Send" to send a message to the server and "Close" to close the connection. 
You can change the message and send multiple times.
<p>
<form>
<button id="open">Open</button>
<!-- <p><input id="input" type="text" value="Hello world!"> -->
<button id="send">Send</button>
<button id="close">Close</button>
</form>
</td><td valign="top" width="50%">
<div id="output"></div>
</td></tr></table>
</body>
</html>
`))

var homeTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>PruneMobile</title>

	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.css"/>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.js"></script>

	<script src="http://kobore.net/PruneCluster.js"></script>           <!-- これ、いずれローカルホストから取れるように換える -->
	<link rel="stylesheet" href="http://kobore.net/examples.css"/>      <!-- これも、いずれローカルホストから取れるように換える -->

	<!-- goのテンプレートのローカルって、どこになるんだろう? -->

</head>
<body>
<div id="map"></div>

<script>

	ws = new WebSocket("{{.}}"); // websocketの確立

	/*
	var print = function(message) {
		var d = document.createElement("div");
		d.textContent = message;
		output.appendChild(d);
	};
	*/

	// 引数にはミリ秒を指定。(例:5秒の場合は5000)
	function sleep(a){
  		var dt1 = new Date().getTime();
  		var dt2 = new Date().getTime();
  		while (dt2 < dt1 + a){
			dt2 = new Date().getTime();
		}
  		return;
	}

    var map = L.map("map", {
        attributionControl: false,
        zoomControl: false
    }).setView(new L.LatLng(35.654543, 139.795534), 18);
    // }).setView(new L.LatLng(35.598563, 139.475528), 18); 広袴

    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
        detectRetina: true,
        maxNativeZoom: 18
    }).addTo(map);

    var leafletView = new PruneClusterForLeaflet(1,1);  // (120,20)がデフォルト

	ws.onopen = function (event) {
	}

	var markers = [];

	//var helicopterIcon = L.icon({ iconUrl: 'http://sintef-9012.github.io/PruneCluster/examples/helicopter.png', iconSize: [48, 48] });
    //var airplaneIcon = L.icon({ iconUrl: 'http://sintef-9012.github.io/PruneCluster/examples/airplane.png', iconSize: [48, 48] });

	// 受信すると、勝手にここに飛んでくる
	ws.onmessage = function (event) {
		// データをJSON形式に変更
		var obj = JSON.parse(event.data);

		console.log("233");	
		console.log(obj.id);
		console.log(obj.lat);						
		console.log(obj.lng);	

		if (obj.id == 0){  // idが未登録の場合
			console.log("obj.id == 0")
			// データをマーカーとして登録
			var marker = new PruneCluster.Marker(obj.lat, obj.lng);

			// 参考資料  http://embed.plnkr.co/WmtpkEqSDJFuFeuiYP54/
			//var marker = new PruneCluster.Marker(obj.lat, obj.lng, {
			//	//popup: "Bell 206 " + i,
			//	icon: helicopterIcon
			//});


			console.log(marker.hashCode);		
			markers.push(marker);
	
			leafletView.RegisterMarker(marker);
	
			console.log(markers);
			console.log(markers.length)

			obj.id = marker.hashCode;
			//ws.send(marker.hashCode); // テキスト送信
			var json_obj = JSON.stringify(obj);
			ws.send(json_obj);			
		} else if ((Math.abs(obj.lat) > 90.0) || (Math.abs(obj.lng) > 180.0)){ // 異常な座標が入った場合は、マーカーを消去する
			console.log("Math.abs(obj.lat) > 180.0)")
			for (let i = 0; i < markers.length; ++i) {
				if (obj.id == markers[i].hashCode){
					console.log(i)
					console.log(obj.id)										
					console.log("obj.id == markers[i].hashCode")

					//leafletView.RemoveMarkers(markers[obj.id]);  // これでは消えてくれません
					// 1つのマーカーを消すのに、面倒でも以下の2行が必要
					var deleteList = markers.splice(i, 1);					
					leafletView.RemoveMarkers(deleteList);

					// 以下失敗例リスト
					//leafletView.RemoveMarkers(markers[i].hashCode);  //これはダメ
					//leafletView.RemoveMarkers(markers[obj.id],'item');
					//leafletView.ProcessView(); // 試しに入れてみる
					//leafletView.RemoveMarkers(markers[i-1]);
					//leafletView.RemoveMarkers(markers);					
					break;
				}
			}
			obj.lat = 91.0;
			obj.lng = 181.0;
			var json_obj = JSON.stringify(obj);
			ws.send(json_obj);				
		} else {
			// 位置情報更新
			console.log("else")
			for (let i = 0; i < markers.length; ++i) {
				if (obj.id == markers[i].hashCode){
					var ll = markers[i].position;
					ll.lat = obj.lat;
					ll.lng = obj.lng;
					break;
				}
			}
			var json_obj = JSON.stringify(obj);
			ws.send(json_obj);	
		}
	}

	// 位置情報の更新
    window.setInterval(function () {
        leafletView.ProcessView();  // 変更が行われたときに呼び出されれなければならない
	}, 1000);

	// サーバを止めると、ここに飛んでくる
	ws.onclose = function(event) {
		//print("CLOSE");
		ws = null;
	}


    map.addLayer(leafletView);
</script>



</body>
</html>
`))