月別アーカイブ: 2016年7月

習うより慣れろprogramingB

高級化の始まり

前回は本日の日付を表示するコードに注目しました。何度、起動しても同じ結果が得られるので面白みに欠けてましたが、わずかなプログラムコードで西暦年、うるう年に対応した大の月、小の月、7曜日などを表示しました。

HelloWorld

今回は、前回の機能に加えて時刻を表示してみます。また、配列を用いて表示文字の色を毎回、変えて表示します。時刻は時々刻々、更新されるので駅前の時刻表示装置に近づき、高級化が始まります。以下に高級化の目玉を上げます。

高級化の目玉

❶表示行が変わるごとに文字の色を変える。
❷現在時刻を表示して結果が時々刻々、変わる。
❸自動開始では説明文を表示できないので、実行開始のボタンを設けた。
❹所定回数の実行後に終了処理を実行する。

Useful

コードの解説

①25行目、開始ボタンを定義。TimeOut関数が起動される。
②7行目、1秒ごとに起動する関数。
③8行目、14回の実行で打ち止め。
④9行目、本日の日付と現在時刻取得関数を呼ぶ。
⑤10~13行目、年、月、曜日、日を求める。
⑥14~16行目、時、分、秒を求める。
⑦22行目、簡易方法で処理を終了させる。

※20行、現状において、Chrome、Fc2のブラウザで正常動作を確認しましたが、Internet ExplorerとMicrosoft Edgeにおいて、setTimeoutの動作が期待通りになりません。また、20行を、setTimeout(‘TimeOut()’, 1000);のように第一引数を引用符で括るとどのブラウザでも期待した動作になりません。

サンプルコード

<html>
<script type="text/javascript">
const DayWeek = ["日", "月", "火", "水", "木", "金", "土"];
const DayColor = ["orange", "powderblue", "red", "sienna", "springgreen", "blue", "magenta"];
var counter = -1;
                                      // Tiny-B.html
function TimeOut(){                   // 1秒ごとに起動する関数
 if(++counter < 14){                  // 14回の実行で停止する
  var date=new Date();                // 今日の日付データを変数dateに格納
  var year = date.getFullYear();      // 年
  var month = date.getMonth()+1;      // 月
  var week = date.getDay();           // 曜日
  var day = date.getDate();           // 日
  var hour = date.getHours();         // 時
  var minute = date.getMinutes();     // 分
  var second = date.getSeconds();     // 秒
  var hiduke = "西暦"+year+"年"+month+"月"+day+"日 "+DayWeek[week]+"曜日 ";
  var jikoku = hour+"時"+minute+"分"+second+"秒 "+"Counter="+counter+"<BR>";
  document.write((hiduke+jikoku).fontcolor(DayColor[counter%7]).fontsize(6));
  setTimeout(TimeOut, 1000);          // 1秒ごとにTimeOut関数を実行する
 }
 else javascript_die();               // finish、簡便式で実行終了
}
</script>
<button onClick="TimeOut();">クリックして現在時刻をご覧ください。</button>
</html>

実行例

 

文法エラーチェック後日談

文法エラーが起きたサンプルコード

<html>
<script type="text/javascript">
var DayWeek = ["日", "月", "火", "水", "木", "金", "土"];
var date=new Date();				//今日の日付データを変数dateに格納
var year = date.getFullYear();		//年・月・日・曜日を取得する
var month = date.getMonth()+1;
var week = date.getDay();
var day = date.getDate();
alert("day"+day):
var hiduke = "西暦"+year+"年"+month+"月"+day+"日 "+DayWeek[week]+"曜日<BR>";
document.write(hiduke);
document.write(hiduke.fontcolor("blue").fontsize(7));
</script>
</html>

エラー発生個所を特定する方法

先日、不可思議な論理積ビット演算で文法エラー発生個所を突き止める泥臭い方法を述べましたが、もっとスマートなやり方が判明しましたので再掲することにしました。

Debugger

アップロードした記事がローカル環境上における動作と著しく異なるときは文法エラーが起きているとみなさなければなりません。記事上で右クリックし、メニューで検証を選択します。上図の①で示したようなメニューが表示されたら、Consoleを選びます。

Uncaught SyntaxError: Unexpected token :   aidesign.lolipop.jp : 287を確認します。

次に②で示したように、Source欄においてSource-SyntaxErrorCheck-(index)メニューを選びます。右欄にソースコードの287が表示されるようにスクロールします。そして、287行が

         
alert("day="+day):

であることを確認します。Unexpected tokenの次の文字に注目し、最後の文字が’;’であるべきところ、’:’になっていることが分かります。

終わりに

思いがけない文法エラーが起きた場合、デバッガーを起動することによって、エラー発生個所が明らかになるスマートな例を示しました。参考になれば幸いです。

習うより慣れろprogramingA

習得のあれこれ

何かを身につけようとして、予算的に余裕がある場合は、○○教室、○○短期集中講座、○○駅前留学などに参加するのも一つの方法です。探せば特典を利用して無料ないし無料に近い料金にてセミナーを受けることができます。

今あるかどうかは定かでありませんが、定年退職時の特典を活用した高額英会話教室を受講した駅前への高齢留学生がいました。

KotowazaJiten

習うより慣れろ
【読み】 ならうよりなれろ
【意味】 習うより慣れろとは、人や本から教わるよりも、自分が練習や経験を重ねたほうが、よく覚えられるということ。

ネットを利用した講座が無数に存在し、意欲があり根気強さを持ち合わせておれば、一定のレベルまでは誰でも到達することが可能です。夏休みが始まったので、習うより慣れろ方式でプログラミングを実践します。

プログラミングの初歩

何をもって初心者というのか判然としませんが、ここでは高度な知識を持たなくても最終的な結果を得られるように、サンプルコードを数多く参照していきます。

熟達者にはどうということもない事柄に初心者は怯え震えて踏み込めないことが多々あります。末尾のQ&Aに『今更、聞けないこと』として、随時、取り上げていきます。

サンプルコードと解説

getFullYear 下に示した14行のサンプルコードをコピー&ペーストして、Tiny-A.htmlを作成します。

次にプログラミングを始めるにあたってで説明した方法で実行すれば、確実に結果が得られます。

上図にDate関数の主な機能を示します。そのなかでgetXXXX()はローカル時間、getUTCxxxx()は協定世界時を扱います。

基本構造 コードの解説になりますが、4行目でDate関数を用いて、本日の日付データを求めます。年、月、日、曜日のうち、月は0~11、日は1~31の値を返します。

このような仕様上の特徴は、何故と感じることもありますが、先に開発して定着させた取り決めを受け入れます。

11、12行にて本日の日付を表示します。夜中の23時59分55秒に実行させ、10秒後に再び実行させた場合に日付が変わっていることを確認できます。

たかが本日の日付表示といえども奥が深いです。ここでは黒と青で表示されますが、曜日ごとに文字の色を変化させるのも一つの楽しみ方です。

<html>
<script type="text/javascript">
var DayWeek = ["日", "月", "火", "水", "木", "金", "土"];
var date=new Date();			//今日の日付データを変数dateに格納
var year = date.getFullYear();	//年・月・日・曜日を取得する
var month = date.getMonth()+1;
var week = date.getDay();
var day = date.getDate();

var hiduke = "西暦"+year+"年"+month+"月"+day+"日 "+DayWeek[week]+"曜日<BR>";
document.write(hiduke);
document.write(hiduke.fontcolor("blue").fontsize(7));
</script>
</html>

実行例

おことわり

文章の中で&、<、>などを小文字で記述するとJavaScriptのタグと解釈され、文章が乱れるので大文字で記述していますが、プログラミングする際には小文字にします。

LearnProgram

Q&A

1Q:プログラミングでスペースはいくつあっても問題ありませんか。
1A:トークン(予約語や演算子など)とトークンの間のスペースは、いくつあっても1個あるいは0個として扱われ、コードの読みやすさに貢献します。”や’に囲まれたスペースはデータとして扱われます。また、改行やタブ(Tab)コードもスペースと同等の扱いになります。
例: var x = y * 256 + z;
var str = “final answer = ” + CalculateValue;

2Q:<head>や<body>がないものもありますが、省略してもいいのですか。
2A:<head>はHTML文書のタイトルやページの説明を行うヘッダ情報を書き込みます。<body>には、文章や画像の詳細な表示内容を記述しますが、タイトルの指定やボタンの定義がない場合は省略することができます。

サンプルコードは紙面の都合もあり、本質でない部分が省略されることが多いので、たくさんのサンプルコードに触れることが上達の秘訣です。

次回の予告

上記サンプルはJavaScriptの動作環境を正しく構築すれば、誰にでも動作確認までこぎつけられたことでしょう。次回からは少しずつ高度化、高級化していきます。

不可思議な論理積ビット演算

ビットについて

Bit

ビットとは情報の最小単位であり、オンかオフ、点灯か消灯、有か無、通電か切電、表か裏などのように二つの状態を表す情報量を言います。

1ビットで2通りの状態を表現できますが、ビットを連ねて組み合わせ4ビットならば16通り、8ビットでは256通り、16ビットでは65536通り、32ビットでは4294967296通りの状態を表現できます。

8bit

ビットを8個連ねた情報単位を1バイトと呼び、アルファベット、数字、特殊記号などをコード化して利用しています。

コンピューターにおいて切電か通電、N極かS極など2つの状態からなる2進数を記憶や演算に用いています。

ビット演算

数の演算において、代表的なものに加算、減算、乗算、除算の四則演算があります。コンピューターの黎明期では加算、減算、乗算に較べ、除算は1桁遅い実行時間がかかりました。そのため、除算命令をなるべく使わないことが推奨されていました。ある数を256で除しその余りを求めるには、255との論理積演算で求めるのが適切とされていました。

Status256

変数のサイズは32ビットに限ったことではありませんが、平均的な例を考えてみます。

上図のビット構成や式で分かるように、変数vを256で割ったときの余りはv%256;で求めることができます。

JavaScriptで同じような試みをしたところ、思わぬ深みに足を取られましたので、ことの顛末を記録することにしました。上の式でwには青部分の下8ビットはゼロになります。

論理積ビット演算と制御処理

ステータス変数
ステータス変数

プログラミングにおいて、処理を実行するとき、その状態をステータス変数に記憶させます。

曲線が描画中かそうでないかは1ビットあれば十分です。それ故、左図のように曲線ごとに割り当てます。今回は6,7,14,15ビットを使用し多くの曲線をサポートすることができます。

描画開始に描画中ビットをonにし、描画完了後にそのビットをoffにしさらに、描画完了ビットをonにします。

特定ビットをゼロにする方法

特定ビットをゼロにするには論理積演算子(&)を使います。
w = v & 0xffffff00; //32ビット変数vの下8ビットをゼロにし、変数wに代入します

文法エラーの例示

SyntaxError2

JavaScriptデバッガが出力するエラーメッセージは上に示したように、具体的でかつ発生個所を指摘してくれます。’;’にすべきところを’:’にして文法エラーになった例です。

エラーメッセージと発生個所
エラーメッセージと発生個所

しかし、時には白地に赤で示したような曖昧なメッセージになることもあり、加えて発生場所の数字がよくわかりません。

今回の全ソース行は283であり、437は何を示すのか不明です。次に明らかにエラーが起きるようにコードを修正してみました。

発生個所を突き止める
発生個所を突き止める

130行でエラーが起きるようにコードとして許されない文字を入れると発生個所の番号が420に変化しました。先の番号よりも17小さくなり、130+17=147行が文法エラーの原因かも知れないと判明しました。

0xffffff00は32ビットの値であり、変数64ビットの処理系では正しい動作となりえず文法エラーとして弾き飛ばしていると推測することができました。

機種依存

環境依存からの脱却

論理積演算を用いたコードはローカル環境では正常に動作することが多いですが、サーバーにアップロードすると文法エラーになり、非常に混乱します。”Uncaught SyntaxError: Invalid or Unexpected token”が出力されます。

JavaScriptのAND演算で誤動作することが多く、w = v & 0xffffff00;に目星を付けます。0xffffff00は32ビットの値であり、変数を32ビットとしたコードは環境依存であり適切ではありません。よって次のように変更します。

w = v & 0xffffff00; //変数を32ビット限定にしている

w = v – (v % 256); //環境依存を避けます

まとめ

ローカル環境で動作確認できれば、あとはアップロードするだけと甘く考えていたら大きな落とし穴に落ち込みました。環境に依存するコードは避けるべきという教訓を得ました。

AND3 今回、文法エラーが起きているとき、何故どこで起きているかを探る手掛かりの一つを紹介しました。参考になれば幸いです。

最後に愚痴をこぼすことが許されるならば、『ローカル環境でも環境に依存するコードは文法エラーとして弾き飛ばしてくれればよいのに』と言いたいです。

自動運転の続き

自動運転の模索後

以前に、自動運転の模索において、自動運転の取り掛かりについて触れました。すでに運転手のいない自動運転タクシーが実験段階にあります。また、外国では公道走行中の自動運転車が思い通りに走行せず、事故を引き起こしたニュースが報道されています。

autodrivetaxi

前回の記述を発展させ、リサジュー曲線(五葉線)とばら曲線上を走行する車の自動制御について考察します。

制御方法

teamovingここで行われる制御は、江戸時代の茶運び人形などにも採用された初歩的な方法です。数メートル離れた客に茶菓子を出すロボットに採用されました。

客は不動であり、あらかじめ客の位置がロボットに教え込まれていました。何かの拍子に客が移動しても追従できません。

お互いに、一定の法則に従った車の動きは相手に逐一、知らされ衝突が起きそうになると、一方の車が進路をゆずる方法です。

2台の車の調整を図る今回の制御は茶菓子もてなしロボットよりは進化していると思われます。

自動運転制御コード

<html>
<head>
<input type="button" onClick=up200() value="updown " style="width:70px;height:30px;">
<input type="button" onClick=t3set() value="速 度 " style="width:70px;height:30px;">
<input type="button" onClick=R1set() value="ずれ差 " style="width:70px;height:30px;">
<input type="button" onClick=T1set() value="安全度 " style="width:70px;height:30px;">
<input type="button" onClick=start() value="開 始 " style="width:70px;height:30px;background-color:pink;">
<font size=5 color='magenta'>自動運転の模索</font><font color='black'><BR></font>
<script type="text/javascript" charset="Shift_JIS">
const HK=30;
const SIZ1=210;
const SIZ2=210;
const ZX=220;
const ZY=220;
const sc=0.0025;	//②ばら曲線
const co2 = ["blue", "yellow"];		//color
const th2 = [3, 2];					//thickness, 6-4, 4.5-3
const co1 = ["tomato", "seagreen"];	//color
const DrvMode=["手動運転", "自動運転"];
const Control=["衝突発生", "衝突回避"];

var ln=0;			//表示行
var t3=4;			//遅延処理
var R1=0.0;			//遅れ位相
var T1=8.0;			//衝突危険域 2.0 4.0 1.9418
var bx = [];		//バラ曲線の軌跡x値を格納, 801
var by = [];		//バラ曲線の軌跡y値を格納
var rx = [];		//リサジュー曲線の軌跡x値を格納, 4007
var ry = [];		//リサジュー曲線の軌跡y値を格納
var driveMode=0;	//0:なりゆき運転, 1:自動制御運転
var max2w=max2=0;	//ばら曲線のポイント数
var max1w=max1=0;	//リサジュー曲線のポイント数
var baraCount=0;	//ばら曲線の連続描画回数
var lissCount=0;	//リサジュー曲線の連続描画回数
var status=0;		//衝突なし
var updown=1;		//up/down
var ctx, wx, wy, vx, vy, first, p, q, img1;

var r=R1;			//0~1.0           |------------128:①リサジュー曲線(五葉線)実行中
var s=0.0;			//0~1.0           ||----------- 64:②ばら曲線実行中
var retry=flag=0;	//flag:98765432109876543210
                                   //||-------------256:②ばら曲線
  img1 = new Image();              //|--------------512:①リサジュー曲線(五葉線)実行終了
  img1.src = "https://aidesign.lolipop.jp/wp-content/uploads/2016/07/AutoDriving.png";//ばら曲線,早めにロードしておく

function initial(){
  var canvas1 = document.getElementById('sample');	//描画コンテキストの取得実行終了
  if (canvas1.getContext) {
	ctx = canvas1.getContext('2d');					//次から具体的な描画内容を指定する
	ctx.drawImage(img1, 5, 10, 440, 357);			//ばら曲線を描画
	ctx.font = "26px Arial";
	ctx.fillText("開始ボタンをクリックして運転開始です。", 3, ZY*2-40);
	ctx.font = "12px Arial";
	ctx.fillText("開始ボタン以外は拡張用です。(ver0.09)", 5, ZY*2-10);
  }
  else	alert("Canvas-error.");
}

function start() {				//開 始
	r=R1;			//0~1.0
	s=0.0;			//0~1.0
	baraCount = lissCount = max1w = max2w = flag=status = retry = driveMode = ln = 0;
	ctx.clearRect(0, 0, 545, 440);
//②ばら曲線の軌跡を求める
  while(s<=10.0015){
	q = s * Math.PI;
	p = 0.4 * q;
	bx[max2]   = ZX + SIZ1 * Math.sin(p) * Math.cos(q);	//x
	by[max2++] = ZY - SIZ1 * Math.sin(p) * Math.sin(q);	//y
	s += sc;											//function1
  }

//①五葉線
var th=0.0;			//0~2.0
var b=0.7;			//para-1
var c=-3;			//para-2
var d=5;			//para-3
var st=0.001;		//step
  for(max1=0; ;){
	var t = th * Math.PI;							//theta
	q = t * d;
	p = 1 + Math.sin(c * q) / 4;					//a
	r = p / 2 * (1 + b * Math.sin(q));				//r
	rx[max1] = ZX + SIZ2 * r * Math.cos(t);			//x
	ry[max1++] = ZY + 25 - SIZ2 * r * Math.sin(t);	//y
	th += st;										//linear function
	if(th > 2.0005)	break;
  }

	first = new Date().getTime();
	flag = 64 | 128;								//②ばら曲線実行中,①五葉線実行中
	head12();
	draw12();										//1:blue, 2:red

	ctx.fillStyle = 'midnightblue';					//塗りつぶしの色
	ctx.font = "14px Arial";
	ctx.fillText("\xA9Aidesign,2016", ZX+HK+70, 20);
}	// end of start()

function up200(){
}

function t3set(){
}

function R1set(){
}

function T1set(){
}

function autoDrive(){
	r=R1;			//0~1.0
	s=0.0;			//0~1.0
	baraCount=lissCount=max1w=max2w=status=retry=0;
	flag = 64 | 128;							//②ばら曲線実行中,①リサジュー曲線(五葉線)実行中
	first = new Date().getTime();
	ctx.clearRect(0, 0, 460, 440);
	++driveMode;								//自動制御運転
	++ln;head12();
	draw12();									//1:blue, 2:red
}

function head12(){
		msg(DrvMode[driveMode]);++ln;
		ctx.clearRect(5, 13, 100, 26);
		ctx.fillStyle = 'darkblue';				//塗りつぶしの色
		ctx.font = "24px Arial";
		ctx.fillText(DrvMode[driveMode], 5, 32);
}

function draw12(){								// <<<<<***** blue ②ばら曲線 64, 256 *****>>>>>
	if((flag&256)==0){	//終了済みか
	  if(max2w<max2){
		vx = bx[max2w];
		vy = by[max2w++];
		var ct2 = baraCount % 2;
		dot(vx, vy, co2[ct2], th2[ct2]);
	  }
	  else{				//終了
		baraCount++;	//ばら曲線の連続描画回数
		//alert("ばら曲線="+flag+" bCt="+baraCount+" lCt:"+lissCount+" MAX1W:"+max1w+" max1="+max1);
		if(lissCount==0){	//①リサジュー曲線(四葉線)が終わっていない
			max2w = 0;
		}
		else{
			flag -= flag % 256;							//flag &= 0xffffff00;
			flag |= 256;
			vx = vy = 999;
			//alert("ばら曲線描画終了 MAX2W:"+max2w+" max2="+max2);
		}
	  }
	}
// <<<<<***** function draw1(), blue ①リサジュー曲線(五葉線)128, 512 *****>>>>>
	if((flag&512)==0){	//終了済みか
	  if(max1w<max1){
		wx = rx[max1w];
		wy = ry[max1w];
		var wk = control2(wx, wy, vx, vy);				//衝突か
		if(wk==0)	max1w++;							//0なら衝突は起きない
		else{											//1なら衝突が起きる状態
			ring("select06");							//ピッ
			if(driveMode==0){
					pentagon(ctx, HK, wx, wy, 'darkmagenta');	//手動運転
					msg(Control[driveMode]);					//衝突発生
			}
			else{												//自動運転
				if(status==0)	retry = 0;
				ctx.fillStyle = ctx.strokeStyle = 'darkgreen';	//線のカラー設定
				ctx.font = "16px Arial";
				ctx.clearRect(wx-60, wy-10, 28, 18);
				ctx.fillText("時間調整" + (retry+1) + '回', wx-123, wy+4);
				ctx.beginPath();
				ctx.lineWidth = 2;
				ctx.arc(wx, wy, HK, 0, Math.PI*2, true);
				ctx.stroke();

				msg(Control[driveMode]+":"+retry);				//衝突回避
				++retry;
			}
			//console.log("STATUS="+status+" wk="+wk+" CT="+retry);
		}
		status = wk;
		var ct1 = lissCount % 2;
		dot(wx, wy, co1[ct1], th2[ct1]);
	  }
	  else {
		lissCount++;	//リサジュー曲線の連続描画回数
		if(baraCount==0){	//②ばら曲線が終わっていない
			max1w = 0;
		}
		else{
			flag -= flag % 256;					//flag &= 0xffffff00;
			flag |= 512;
			wx = wy = 0;
		}
	  }
	}
/////////////////////////////////////////////////////////////////////
	var time = new Date().getTime() - first;	//実行時間を計測
	ctx.fillStyle = "green";					//塗りつぶしの色
	ctx.font = "14px Arial";
	ctx.clearRect(2, 40, 78, 16);
	var tm = "     "+time+"ミリ秒";
	ctx.fillText(tm.substr(tm.length-8, 8), 5, 55);
  if(flag < 768)	setTimeout(draw12, t3);
  else{
	//alert("driveMode="+driveMode);
	if(driveMode==0)	setTimeout(autoDrive, 1000);
	else				msg("運転終了");		//すべて終了
  }
}			// end of draw12()

function dot(x1, y1, col, thickness){
	ctx.fillStyle = col;						//塗りつぶしの色は赤
	ctx.fillRect(x1, y1, thickness, thickness);
}

function control2(gx, gy, hx, hy){				//衝突チェック-自動制御処理
		var w = 0;
		var ux = gx - T1;
		var px = gx + T1;
		var uy = gy - T1;
		var py = gy + T1;
		//console.log("VX=%d VY=%d  U1=%d V1=%d  U2=%d V2=%d", hx, hy, ux, px, ux, py);
		if(hx>=ux){
		  if(hx<=px){
			if(hy>=uy){							//衝突が起きる
			  if(hy<=py){						//衝突発生
				w = 1;							//増分なし、衝突回避に時間調整
			  }
			}
		  }
		}
	return w;
}

function pentagon(ctx, hk, px, py, color){
const DT=36;							//5角形, DT=360/(5*2)
const R=0.382;
var x=[];
var y=[];
	for(var i=0; i<10; ++i){
		var t=(i*DT+90)*Math.PI/180.0;
		if(i % 2){
			x[i]=R * Math.cos(t);
			y[i]=R * Math.sin(t);
		}
		else{
			x[i]=Math.cos(t);
			y[i]=Math.sin(t);
		}
		x[i] = px + x[i] * hk;
		y[i] = py - y[i] * hk;
	}
	ctx.beginPath();					//パスの描画を始める
	ctx.moveTo(x[0], y[0]);				//線の開始位置 (xの座標値 , yの座標値)
	for(var j=1; j<10; ++j)	ctx.lineTo(x[j], y[j]);
	ctx.lineTo(x[0], y[0]);
	ctx.closePath();
	ctx.fillStyle = color;				//線のカラー設定
	ctx.fill();							//線の終了
}

function ring(tune){
	document.getElementById(tune).play();
}
function msg(tx){
		ctx.fillStyle = 'darkgreen';				//塗りつぶしの色
		ctx.font = "14px Arial";
		ctx.fillText(tx, 460, (ln++)*14+14);
}

window.onload = initial;
</script>
</head>
<body>
<canvas id="sample" width="550" height="440" style="background-color:snow;border:1px solid green;float:left;"></canvas>
</body>
<audio id="select06" preload="auto"> <source src="https://aidesign.lolipop.jp/wp-content/uploads/2014/11/lock3.wav"> </audio>
</html>

自動運転例

自動運転の模索

訪問者数と遊び心

数を競う

accesscounter21世紀が産声を上げたころ、ホームページやブログの訪問者数を競う風潮にあり、右図のようなアクセスカウンターを表示することが流行りました。

今では数を競うよりも中身の充実度を重要視するようになりました。

検索エンジンのBOT(ボット、ロボットから転じて使われた)など人間に代わって作業を行うコンピュータープログラムにより、計数値が異常に上がったりして数自体も信用性が薄らいでいます。

遊び心

そうはいっても、訪問者数やページビュー数を評価の参考にしているサイト運営者が多いと思われます。訪問者数をそのまま表示しても面白みが少ないので、ページビュー数が500キリ番になったとき、幸運の証として特別な表示が現れる仕組みを施しました。

ページビュー数がたとえば、231000,231500,232000になったとき、カテゴリ別に記事タイトルが表示される直前に、下のような幸運を呼ぶ図が現れます。

PageView

仕組み

ページビューカウンター、訪問者カウンター、IPアドレスを保存するファイル(例えばcount.txt)を用意します。訪問者カウンターはIs_user_logged_in()関数を使うと、WordPressで会員制サイトを作った際、カスタマイズに利用することができます。

このカウンターは解析用に設置しており、直前にアクセスしたIPアドレスと今回のアドレスが異なるときに、カウントアップされます。

アクセスカウンターの仕組み

カウントアップコードは記事を閲覧する大元に設置しているので、ページビューカウンターは無条件にカウントアップされます。今回はサイトマップの固定ページに挿入しました。

よって、記事のURLアドレスをブラウザの入力欄に直接、指定して閲覧した場合は、二つのカウンターは増加されません。

サンプルコードで苦心した点

phpコードでファイルへの書込みや読込みをする場合、fwrite,fread関数を用います。アクセスモードはテキストが基本です。カウンターの値が大きくなると総桁数が大きくなり変動するので、複数回の書込みや読込みで問題動作を引き起こします。

そこですべての項目をテキストイメージで保存し、項目をカンマで区切った一つだけのレコードにします。そして、読込み時にexplode関数を用いて文字列をデータに分割し配列に格納します。

考察

このたび、アクセスカウンターコードをサイトマップの記事に設置したので、ページビューカウンターが実態より少なめに表示されます。これはWordPressのソースコードに手を加えたくなかったからです。

もっと正確なページビューカウンターを把握するには、これらのコードをWordPressシステムコードのfunctions.phpに入れるようにすれば精度の高いアクセスカウンターが実現できるものと思われます。

サンプルコード

<?php
  $total = array(0, 0, 0);               // 0:$pageview, 1:$count, 2:$ipaddress
                                         // 閲覧ページ数 訪問者数  IPアドレス
  $file_name = "count.txt";

  $ip = $_SERVER["REMOTE_ADDR"];         // IPアドレスを取得する
  if( file_exists($file_name) ){
    $handle = fopen($file_name, 'r');    // ファイルを読み込む
    $t = fread($handle, 128);            // ページビュー他のデータをファイルから読み込む
    $total = explode(",", $t);           // 文字列を分割
    $total[0] = $total[0] + 1;           // ページビューの数字を無条件に増やす
    fclose($handle);                     // ファイルを閉じる

    if($ip != $total[2]){                // 新規訪問者とみなす
      $total[1] = $total[1] + 1;         // 訪問者の数字を増やす
      $total[2] = $ip;                   // IPアドレスを更新する
    }
  }

  $t = $total[0].",".$total[1].",".$total[2];// 書き込む文字列を連結

  $handle = fopen($file_name , 'w');     // ファイルを書き出し用にオープンする
  if($handle){
    if(flock($handle, LOCK_EX)){
      $outn = fwrite($handle, $t);       // 文字列を書き込む
      if($outn === FALSE){
            echo('ファイル書き込みに失敗しました');
      }
      flock($handle, LOCK_UN);
    }
    fclose($handle);                     // ファイルを閉じる
  }
?>

// ここに閲覧ページ数($total[0])や訪問者数($total[1])を参照して、適切なコードを追加します。



「ありがとうございました」に次はない

動機

最近、Windows 10 Mobileのシャットダウン時の「ご利用ありがとうございました」というメッセージが話題になっています。この話題にことよせて、言葉の重み、特に過去形で締めくくるのか現在形で終わるのかについて思いを綴ります。

ご利用ありがとう

例証

SoftBank会話において、これからも良好な関係を継続したいと思うときは、耳障りな言葉を発しないという気配りをすべきです。

プロ野球のインタビューでは春のキャンプ時にも専門家のアドバイスを受けたかのようにそつのない受け答えが多いと感じます。以下に気になる例を挙げます。

①スーパーやデパートの閉店時、出口で店員から「ありがとうございました」と感謝のお辞儀をされます。

②あるスポーツ選手がインタビューの冒頭で試合の活躍を評価され、「ありがとうございました」と応答します。

③スポーツ解説者がアナウンサーから選手の活躍の解説を求められたとき、「いや」という口癖から会話を始めます。

④ある営業マンが会話を始めるとき、いつもの口癖の「実は」から話し始めます。

⑤市役所で自分の用事で窓口に出かけたのに、「ご苦労様」と上から目線の言葉を掛けられます。言われた方は全くうれしくないのです。違和感を感じます。

⑥人命に関わるような突発事故発生時に、「就業規則違反になる」と言って人助けに加わりません。

独善的な解説

例証に独善的な説明を加えます。

❶「ありがとうございました」という感謝の言葉はあまりにも普通ですが、なにか1回限りのような気がします。二度目がなくても構いませんとのニュアンスを感じます。

伸びる会社
伸びる会社

商売はリピーターによって支えられるとも言われ、二度以上の来客はありがたいはずです。「ありがとうございます」、「いつもありがとうございます」という方が優れています。

これには実話があります。ある新興スーパーの話で未上場、東証二部上場、東証一部昇格と順調な業績を重ねています。

《「ありがとうございました」でなく「ありがとうございます」と言って来客に感謝しなさい》と朝礼で訓示があったと聞きました。

感謝の言葉の先頭に「まいど」「いつも」を加えると過去形での言い回しが不自然に感じます。

❷前項とほとんど変わりませんが、「ありがとうございました」はインタビューの最後ならば、違和感は少ないですが、過去に何度かインタビューを体験したり、体験ゼロでも、これからたびたびあるかも知れないとの思いが強ければ、「ありがとうございます」がより適切と思われます。

口癖現在形にすると、今回に対するお礼とこれからもよろしくお願いしますとの意を汲み取ることができます。

❸「いや」、「いな」、「しかしながら」、「でも」などの反語は、最終的には肯定するのだが、否定から始めてその差を強調する場合などに使われると感じています。

それなのに口癖で「いや」から始められると直前の会話が否定されたかのように感じられ、穏やかでない雰囲気になります。

詐欺師の定番せりふ❹「実は」は今まで表に出さなかった(隠していたのだ)が、「これから正しいことを言います」とのニュアンスを感じさせます。

いままで欺いてごめんなさい、あなただから真実を話します、選ばれた人だけに打ち明けますなど良くも悪くも不透明な雰囲気を醸し出しています。多用すると信頼度はゼロになります。

❺事務的な言葉にも暖かみがないと時代の流れに乗り遅れます。

❻何とかの一つ覚えのごとく、野暮な行動の言い訳にありふれた言葉を使うのはいかがなものでしょうか。優先順位を考えた行動、バランスの取れた行動を心がければ何をすべきかは明らかになります。

おわりに

最後に元気の出る音楽を聴きながら締めくくりましょう。

タイトル:《太陽の実り》 フリーBGM DOVA-SYNDROME 作曲者:ilodolly

作曲者のことば:『ケルト風の明るい楽曲です。作物がたくさん実り、それを収穫し喜んでいるという場面をイメージして制作しました。』

広告塔 その人が怪しいかそうでないかは一挙一動で分かると言われています。たまに見込み違いもあります。

軽く使っている口癖が違う意味にとられることは損です。

自分の口癖が会話の相手にどう伝わっているかを検証する機会になれば幸いです。

大学のスポーツイベントにおける優勝者インタビューでも、適切なレクチャーを受けていればもう少しアピール度の高い受け答えをしたことでしょうと感じるときがあります。受験生誘致にしのぎを削っている昨今、広告塔の役割に総合的な経営戦略を加味してもよいのではと考えます。

進化したプログラミング

実用的なアプリ

子犬のワルツ

昔であればレコード、今ならCDがあれば、Windows Media Playerなどを使って聴きたいときに聴きたい音楽を聴くことができます。

電子式福引き機により、あたりくじに応じた音楽を鳴り響かせたい時や誕生日の朝7時に、当人のお気に入り音楽を自動的に流すには専用のアプリを作れば解決します。

前回の《プログラミングを始めるにあたって》において、準備するツールや予備知識について語りました。今回は実用的なもう少し進化したJavaScriptプログラミングを考えてみます。

子犬のワルツ・冒頭譜面

プログラミングのねらい

音楽会の演奏画像を描画するなかに、音楽記号をランダムに表示し、クラシック曲を流します。何度も再生可能なように仕立て上げます。

プログラムコード

<html>
  <head>
  <font size=6 color='violet'>『小犬のワルツ』発表会</font>
  <font size=4 color='royalblue'>&copy;Aidesign,2016, V0.12</font><BR>
	<script type="text/javascript" charset="Shift_JIS">
	const TM=200;								//Concert.html
	const SIZE=80;
	const SONG0="&nbsp;&#9632&nbsp;<font color='red'>停止";
	const SONG1="&nbsp;&#9658&nbsp;<font color='red'>開始";
	const SONG2="ショパン作曲、ワルツ第6番『小犬のワルツ』:";
	var img2 = new Image();
	img2.src = "https://aidesign.lolipop.jp/wp-content/uploads/2016/07/Live.png";		//演奏会
	var img0 = new Image();
	img0.src = "https://aidesign.lolipop.jp/wp-content/uploads/2016/07/ncnMusic2.png";	//音楽記号
	var ctx=0;
	var canvas;
	var pbar;
	var ptxt;
	var pupp;
	var paud;
	var pcom;
	var timerid = setInterval('draw()', TM);	// ファイル読込み待ちのため、処理を遅らせる
	var x = 0;					 				// x-position
	var y = 50;									// y-position
	var ct = 0;									// counter

	function draw(){							//演奏会や音楽記号を描く関数
		canvas = document.getElementById('tutorial');
		if (canvas.getContext){
		  if(ctx==0){
			paud = document.getElementById('songname');		//audioオブジェクトを取得
			pbar = document.getElementById('prog');			//プログレスオブジェクトを取得
			ptxt = document.getElementById('outp');			//テキストオブジェクトを取得
			pcom = document.getElementById('command');		//開始・停止オブジェクトを取得
			pcom.innerHTML=SONG2+SONG1;			//開始
			ctx = canvas.getContext('2d');
			ctx.drawImage (img2 , 0, 0, 642, 360);	//演奏会を描画
			timerid = setInterval('draw()', TM);
		  }
			NumericDisplay((ct++) % 6);			//音楽記号を描く
		}
	}
	function StopStart(target){					//timeridが1以上で確定処理
		console.log("StopStart="+timerid);
	  if(timerid){								//確定処理
		pcom.innerHTML=SONG2+SONG0;				//停止
		pupp = setInterval("upPrgrss()", 400);
		paud.play();							//音楽開始
		clearInterval(timerid);
		timerid = 0;
	  }
	  else{										//再開処理
		pcom.innerHTML=SONG2+SONG1;				//開始
		paud.pause();
		timerid = setInterval('draw()', TM);
	  }
	}
	function upPrgrss(){
	  if(pbar.value<pbar.max){					//進行中
	    pbar.value = Math.round(paud.currentTime / paud.duration * 100);
	    ptxt.value = pbar.value;
	  }
	  else{										//実行終了
		pcom.innerHTML=SONG2+SONG1;				//開始
		paud.pause();
		paud.currentTime = pbar.value = ptxt.value = ctx = 0;
		timerid = setInterval('draw()', TM);
	  }
	}
	function NumericDisplay(n){					//n:0~5
	  var w = Math.floor(Math.random() * 20);	//0~19までの乱数を発生させる
	  x = n * 105 + 20;
	  var wx = w % 10;							//0~9
	  var wy = Math.floor(w / 10);				//0~1
	  ctx.drawImage (img0 , 100*wx, 100*wy, 100, 100, x, y, SIZE, SIZE);	//音楽記号を描画
	}
	</script>
	<style type="text/css">
	  canvas { border: 1px solid #999; }
	</style>
  </head>
  <body>
	<canvas id="tutorial" width="642" height="360"></canvas>
	<BR><a id="command" href="javascript:void(0)" onClick="StopStart();return false;"></a>&nbsp;&nbsp;&nbsp;&nbsp;
	&nbsp;&nbsp;&nbsp;&nbsp;<progress id="prog" max="100" value="0"></progress>&nbsp;<output id="outp">0</output>%
  </body>
<audio id="songname" preload="auto">
 <source src="https://aidesign.lolipop.jp/wp-content/uploads/2016/07/Chopin-MimuteWaltz.mp3"> </audio>
</html>

コードの解説

HTMLとは①1行:html文書であることを明示する。

②3~4行:htmlのfontタグでテキストを表示する。

③5行:scriptコードを記述すると宣言。文字コードはシフトJISで保存される。

④6~10行:定数を定義する。

⑤11~14行:画像や音響ファイルを先読みする。

⑥15~25行:変数を定義する。varはローカル変数を定義するものだが、最外側で定義しているので13~24行の変数はグローバル変数になる。

⑦22行:draw関数で使う画像ファイルの読込みが終了するのを待つために、setInterval関数を利用してdraw関数を起動する。

⑧27~42行:draw関数で演奏会の画像を描画したり、楽譜記号を描く。

SHOPIN ⑨43~57行:曲の再生を開始/停止する処理。

⑩58~69行:演奏の進行を表示する。

⑪70~76行:楽譜記号を描く関数。

⑫77行:script定義の終了。

⑬78~80行:cssを定義する。

⑭83行:canvasを定義する。

⑮84~85行:曲の開始/停止を処理する。

⑯87~88行:オーディオファイルの読込み仕様を定義する。

⑰89行:html文書の終了。

おわりに

実用性を考慮したプログラミングとして、著作権の心配がないクラシック、ショパン作曲、ワルツ第6番『子犬のワルツ』を取り上げました。

プログラミングとしては高度な部類に属すると言えます。画像や音響データファイルのサイズは大きく、読込み時間を必要とします。動作の手順を考えておかないと音や画像が出ないことがあります。

また、演奏終了後にふたたび再生可能なようにするとコードサイズがどうしても大きくなります。その他にポスター画像としてサムネイルを表示すれば、実用的なアプリケーションに近づくものと思われます。

再生

『小犬のワルツ』発表会 ©Aidesign,2016, V0.12

          0

プログラミングを始めるにあたって

インタープリター

プログラミング言語において、プログラムコードに直接、働きかけて即、実行結果を得られる翻訳言語ツールをインタープリターと言います。インタープリターではBASICという言語が一世を風靡した時代があり、ビル・ゲイツ氏はBASICをパソコンへの移植にトップを切って成功し大富豪への道を開きました。

コンピューター言語の種類
コンピューター言語の種類

インタープリターとスクリプトとの違いやインタープリターと対比するコンパイラについての論評は他の記事に譲ります。

JavaScriptについて

Webアプリケーションの開発言語には、Java,JavaScript,C#,C++,PHP,Python,Rubyなどがあります。開発言語の利用率において、ソフトウェア開発プロジェクトのための共有ウェブサービスであるGitHub(ギットハブ)の発表では、JavaScriptが第一位を占めています。

JavaDcriptBASICは先頭のBがBeginnerであったためか、初心者にも理解しやすいなどと喧伝されましたが、当初のBASICはブロック構造という考えがなく、GOTO文を多用し拡張性を考慮していないなどの不満が高まり、次第に利用率が低下しました。

対して、JavaScriptは多くの言語の優れたところを取り入れ、ここ数年、Webアプリケーションの開発としてクローズアップされています。

長年、多くの言語に親しんできましたが、JavaScriptによるプログラミングは少ないプログラムコードで制御や処理を実現できるという特長があります。

かなり昔のアセンブリ言語によるプログラムに比べると1/10おろか1/100のコンパクトサイズになっています。オブジェクト指向言語の処理系が多くの機能をライブラリに内包しているので、黎明期の言語に比べてプログラミングのしやすさが格段に向上しています。

JavaScriptによるプログラミングの準備

JavaScript基本編プログラミングを始めるに当たり、JavaScriptを選ぶのも一つの方法です。準備のための経費はゼロといってもよいでしょう。用意するものを以下に示します。

①テキストエディタを用意する。パソコンについているメモ帳で十分だが、大作のアプリ開発に備えフリーソフトGreenPadなどが推奨される。

②「設定」の「コンテンツの設定」からJavaScriptを有効にする。
Google Chrome以外では、JavaScriptを有効/無効にする方法 が参考になる。

③HTML5の仕様に則ったJavaScriptコードファイルを作成し、ファイル拡張子をhtmlにして保存する。

例えばSample.htmlを作成する。下に挙げたコード2例を含め、ブログや解説書に掲載されている動作確認済みのサンプルコードをコピー&ペーストする。

④エクスプローラーなどのファイル管理ツールで保存したファイルにカーソルを当て、JavaScriptプログラムを実行する。JavaScriptを有効にした場合、拡張子がhtmlであればJavaScriptが実行される。

⑤首尾よく実行になったら、少しずつ機能を強化するなど高級化を図る。

本格化への移行

プログラミング解説書
プログラミング解説書

サンプルコードを走らせるまでは容易に進むことができます。機能の高いアプリケーションを作成するには、多くの先達が発表している既存のプログラムコードに接することにつきます。

そのコードを入手して動作させましょう。その際、ファイルの保存文字コードに気を配ることが必要です。文字コードはShift_JISかUTF-8コードが多いです。シフトJISはアンダースコア(_)でUTFはハイフン(-)を使うことを知らなければなりません。

大作を開発するには機能の高いテキストエディタプログラミング解説書の一読も欲しいところです。

サンプルコード

以下に等差数列の総和をJavaScriptで求めるコードです。等差数列の総和はn*(n+1)/2で求めることができますが、0~9までを10回加算して算出しています。求めた結果を合計値と計算値として表示します。

<html>
<script type="text/javascript" charset="Shift_JIS">
	var t = 0;					// 合計値
	for(i=0; i<=9; ++i){
		t += i;
		document.write("I = "+i+"  T = "+t+"<BR>");
	}
	var w = 9 * 10 / 2;			// t = n * (n + 1) / 2;
	document.write("合計値 = "+t+" 計算値 = "+w);
</script>
</html>

考察

等差数列の和10項の等差数列の総和は10回の繰り返し加算でも算出時間はかかりませんが、項数が100万にもなるとそれなりの時間がかかるので、n*(n+1)/2による算出が優れています。

 

単純な加算が重要な役割をする例を次項で示します。n回繰り返しによる算出方法は次のような場合に必須です。

10個の配列の総和を求める等差数列総和

規則性のあるデータの集まりを配列といいます。たとえば、10個の箱に入っているボールの合計を求めるには、10回の加算をします。前回のサンプルコードを改良し、配列の扱いをコードに反映させます。

10個の箱
10個の箱

10個の箱に入っているボールの数に規則性がないのならば、地道に加算することになります。

サンプルコード2

規則性のないところに、アルゴリズムは成立しません。愚直に配列要素の値を加えていきます。10個の箱のボール数を加算し、合計総数を表示するJavaScriptコードを示します。

<html>
<script type="text/javascript">
	var t = 0;					// 合計値
	var box=[3, 4, 1, 2, 1, 2, 4, 1, 3, 2];
	for(i=0; i<=9; ++i){
		t += box[i];
		document.write("box["+i+"] = "+box[i]+"  T = "+t+"<BR>");
	}
	document.write("合計値 = "+t);
</script>
</html>

サンプル実行結果

サンプル実行結果

おわりに

JavaScriptは言語仕様の制定などにおいて、全世界の技術者が協力して作っており、BASICの立ち上がり時とは趣を異にしています。デバッグの環境も整備されています。

JavaScriptなどのスクリプト(インタープリター)言語は、ソースコードが丸見えになるという問題点を残しているものの、アプリケーションの開発には極めて効率の良い言語であるといえるでしょう。

マンドリン演奏

マンドリンとは

MandlinGuitan3マンドリンは弦楽器のひとつで、4複弦(8本)からなるギターよりも小ぶりな楽器です。

ギターのように和音を奏でることは苦手な楽器で、主にメロディーを担当しソロ演奏よりも合奏に似合います。

イタリアなどで普及したようです。ロシアには音質がマンドリンに似ていて、形が角ばったバラライカと呼ばれる弦楽器があります。

合奏の楽しさ

楽器演奏は合奏が圧巻の楽しさです。鍵盤、木管、金管、弦楽器のほかにリズム楽器などがあり、指揮者のもと、全員の呼吸が一致したときは最高の気分になります。

mandlin-99

複数の弦楽器、管楽器および打楽器の編成による音楽を演奏するオーケストラにおいて、コンサートマスターといえば第1ヴァイオリンの演奏者が務め、演奏前のチューニング(音合わせ)をまとめます。

マンドリンはヴァイオリンやピアノなどの楽器に比べて地味な存在です。それでも、マンドリンを中心にしたマンドリンクラブが作られ、演奏会が開催されます。

TriAngle合奏では打楽器やトライアングルが加わると演奏に厚みや深みが増し、強い印象を与えることとなります。

過去の作曲者がマンドリンをフィーチャーする(特徴づける、際立たせる)大曲を手がけたことは多くありませんがないことはないのです。

マンドリンをフィーチャーした曲

マンドリンのクラシック曲に《ヴィヴァルディ:マンドリン協奏曲 ハ長調 RV.425 第1楽章
》があります。ヴィヴァルディは江戸時代、4代徳川家綱将軍の頃に生まれた音楽家であり、先の協奏曲を残しています。

上記曲の著作権は戦時加算条項など戦争の負の遺産を加えたとしても、とうの昔に消滅していますので、以下に掲載します。

作曲者が死後、50年や70年を超えていても、編曲者や演奏者が現存している場合もあり、著作権の扱いは厄介です。ヴィヴァルディの名曲を聴くには、イ・ムジチ合奏団によるヴァイオリン協奏曲『四季』が有名ですが、たまにはマンドリン協奏曲に想いを寄せましょう。

マンドリンのクローズアップ

下町の太陽古い話で恐縮ですが、倍賞千恵子の青春歌謡曲《下町の太陽》でマンドリンが一躍、注目を浴びました。青春の一ページです。

マンドリンといえば、『丘を越えて』の作曲家・古賀政男氏の功績が評価されます。

ある市民会館で開かれたM大学マンドリン演奏会において、ショスタコーヴィチ作曲『ジャズ組曲第2番~第2ワルツ』を聴き、感動にひたりました。