2015年11月3日火曜日

Javascriptでピタゴラス数を求める

普段管理人が通う学校の教師の提案で、「ピタゴラス数」を求めるプログラムを作ってみました。

ピタゴラス数って何?って方はWikipedia - ピタゴラス数をご覧ください。

ここでのmnは、ピタゴラス数の面積を求めるのに使用する自然数(m > n)とします。

では、さっそく実物を。

mまたはnの最大値 

処理結果

mの値 nの値 斜辺(m2 + n2) 他の一辺(m2 - n2) 他の一辺(2mn) (参考) 面積 (参考) mとnのG.C.D

参考程度にソースコードをはっておきます。

<!--
  <script>~</script>間はコメントアウトを省略
  しています。
-->
<script type="text/javascript">
function tagainiso(){
  // 剰余
  var r;
  var tagainiso_n = n;
  var tagainiso_m = m;
  gcd = 1;

  while ((r = tagainiso_m % tagainiso_n) != 0) {
    tagainiso_m = tagainiso_n;
    tagainiso_n = r;
  }
  gcd = tagainiso_n;
  if(gcd != 1) {
      n = n / gcd;
      m = m / gcd;
  }
}

function pitagras(){
  // 乱数その1
  m = Math.floor(Math.random()*document.getElementById("max").value + 1);
  //その2
  n = Math.floor(Math.random()*document.getElementById("max").value + 1);

  if(m < n) {  // m >= nにする
    var taihi = m;  //一時退避
    m = n;
    n = taihi;
  }
  tagainiso();
  //テーブル取得
  var table = document.getElementById("area");
  //行追加
  var tr = table.insertRow(-1);
  //セル挿入
  tr.insertCell(-1).innerHTML = m;
  tr.insertCell(-1).innerHTML = n;
  tr.insertCell(-1).innerHTML = m * m + n * n;
  tr.insertCell(-1).innerHTML = m * m - n * n;
  tr.insertCell(-1).innerHTML = 2 * m * n;
  tr.insertCell(-1).innerHTML = ( (m * m - n * n) * 2 * m * n ) / 2;
}
</script>

<p><b>m</b>または<b>n</b>の最大値&nbsp;<input type="number" size="5" id="max" value="50"></p>
<p><button onclick="pitagras()">実行</button></p>
<p>処理結果<br>
<table id="area" border="1">
  <tr>
    <td>mの値</td>
    <td>nの値</td>
    <td>斜辺(m<sup>2</sup> + n<sup>2</sup>)</td>
    <td>他の一辺(m<sup>2</sup> - n<sup>2</sup>)</td>
    <td>他の一辺(2mn)</td>
    <td>(参考) 面積</td>
  </tr>
</table>
</p>

作り方を知りたい方は、コメントいただければ解説します。

2015年10月29日木曜日

Javascriptで最大公約数を求める(ユークリッドの互除法)

今回は、数学的なお話。ユークリッドの互除法をJavascriptでしてみようと思います。

まず...
ユークリッドの互除法とは?という方へ。

ユークリッドの互除法は、簡単に最大公約数を求めるための計算法です。説明より例を示した方がいいかと思いますので、例題を一つ。
(例題) 1071と1029の最大公約数を求めよ。

  • 1071 を 1029 で割った余りは 42
  • 1029 を 42 で割った余りは 21
  • 42 を 21 で割った余りは 0
  • よって、答えは 42

では、これをプログラムに書き起こしてみましょう。関数名は最大公約数の略であるG. C. D.としました。

function gcd(m, n) {
  // 剰余
  var r;

  if(m < n) {  // m >= nにする
    r = m;  //一時退避
    m = n;
    n = r;
  }

  while ((r = m % n) != 0) {
    m = n;
    n = r;
  }

  return n;
}

2015年10月28日水曜日

C#で外部スイッチとやり取りする

パソコンと(2極)スイッチで通信する方法を考えてみました。(動作未確認)
※2極スイッチとは、簡単なON/OFFだけを切り替えるスイッチのこと。

そんなとき問題になるのは、

  • パソコンとスイッチをどうやって繋ぐか
  • ソフト側でどうやってON/OFFを認識するか
です。

まず考えたのは、USBで接続する方法。USBポートでスイッチと接続できないかと。しかし、これではドライバを作らないといけないし、スイッチ側に自己紹介する機能を持たせなければやり取りは不可能です。

次に考えたのがシリアルポートを使う方法です。1ビットのシリアル接続が可能なら、ON/OFFも可能なのではないか。
結論から先に書くと、「できました」。

RS-232C規格のシリアルポートを使った具体的なしくみです。
まず、DTR線の状態をONにしておきます。スイッチはDTR-(スイッチ)-DSRの順で接続しておきます。スイッチがONになると、DTRから出力された12Vの電流がDSRに流れることになります。スイッチをOFFにしたときは-12Vが正確に入力されるわけではありませんが、電流0はFalse扱いをうけるようです。

その理論(?)をもとに、C#でコードを書いてみました。

using System;

// シリアルポートクラスがある名前空間
using System.IO.Ports;

namespace myPort
{
  public class myPort1
  {

    // シリアルポートクラスのインスタンス
    SerialPort port = new SerialPort("COM1");

    // ポートをオープンする
    port.Open();

    // DTR線を出力
    port.DtrEnable = true;

    // ONかOFFかは次の値で確認する
    port.DsrHolding;

    // 例
    private void checkSwich(){
      if(port.DsrHolding)  // ON
      {
        MessageBox.Show("スイッチはONです。");
      }
      else
      {
        MessageBox.Show("スイッチはOFFです。");
      }
    }
  }
}

これで、ON/OFFの2極スイッチとパソコンとでやり取りができるようになりました。

なお、この記事を書くにあたって、どこでも発車ベルヘルプ - スイッチのつなぎ方を参考にいたしました。
ありがとうございました。

なお、この記事で記載された内容は、管理人(chiko ryo)では動作確認を行っておりません。くれぐれも自己責任でお願いします。また、このサンプルは著作権フリーですが、これを参考にしていかなる損害が出たとしても管理人(chiko ryo)は責任を負いませんのでご容赦ください。

2015年10月27日火曜日

JavascriptでINIファイルを解読する その3

JavascriptでINIファイルを解読するシリーズの第3弾です。

前回のJavascriptでINIファイルを解読する その2でお約束していた通り、INIを読み込んで連想配列に返す関数を完成させることができました。

さっそく、ソースをはります。

function myReadInI(myFname){

    var i = 0; // プロパティiはカウンタです。
    var t = null; // コメント除去に使用します。
    var ts = 0;   // これもです。
    var sec = null; //処理中のセクションを記録
    var pal = null; //処理中のパラメータ名を記録
    var returnData = {}; //返り値
 
    // オブジェクト生成
    var objFileSys = new ActiveXObject("Scripting.FileSystemObject");
 
    var objTextStream = objFileSys.GetFile(myFname).OpenAsTextStream(1, 0);
    /*読み込みモードを使用、文字コードはUnicodeです。(Unicode文字が扱えるようにするため)*/
 
    var data = new Array(); // 空の配列
 
    // ファイルが最後まで読み込まれるまでループ  読み込み
    while (!objTextStream.AtEndOfStream) {
 
        t = objTextStream.ReadLine();
        ts = t.indexOf(";"); // コメントを探す
        if(ts == -1){ // コメントがない
            data[i] = t;
        }else{ // コメントあり
            data[i] = t.substring(0, ts);
        }

        //解読

        if(data[i] != ""){  //空行でないか?

            if(data[i].indexOf("[") == 0){  //セクション行

                sec = data[i].slice(1, -1);    //セクション名を抽出する

                returnData[sec] = {}  //さらにパラメータ名の2次元連想配列が作れるようにする

            }else{                          //パラメータ行

                if(data[i].indexOf("=") != -1){  // "="を含む行であることを確認する

                    /* パラメータ名と値を分割(pal[0]がパラメータ名、pal[1]が値) */
                    pal = data[i].split("=");

                    /* 連想配列に代入する */
                    returnData [sec] [pal[0]] = pal[1];
                }

            }

        }
        i++;
    }

    return returnData;

}

前回からの変更点として、

  1. 引数が一つになった
  2. 戻り値が2次元連想配列になった
  3. 若干軽くなった
  4. 何度もファイルを読み込みなおす必要がなくなった
があげられます。また、空行があってもそのあとの行も読み込むようになったほか、セクションの閉じカッコ"]"の省略を禁止しました。


使い方
・引数

引数は1つ必要です。INIファイルまでのパス(絶対パス・相対パス)を文字列で渡します。
・戻り値
INIを解析した結果の2次元連想配列を返します。設定内容は(戻り値)["(セクション名)"]["(パラメータ名)"]で取得できます。

おそらくこのシリーズは今回で終わりとなります。
解説は要望があれば行います。ご希望であればコメントをお願いします。

Javascriptでテキストファイルを読み込む

近年、Javascriptがブームになりつつあります。FileAPIなどの拡張機能なども充実してきました。
そこで、IE独自のActiveXコントロールを使って色々なことをしてみましょう。

今回は(次回があるといいですね)テキストファイルの読み込みをしてみようと思います。

ファイル操作関連のことは、次のインスタンスを多くの場合使用することになります。

var hogehoge = new ActiveXObject("Scripting.FileSystemObject");

WSHの場合は、以下のようになります。

Set hogehoge = WScript.CreateObject("Scripting.FileSystemObject");

これで、ScriptingFileSystemObjectクラスのインスタンスを取得できました。ファイル操作は主にこいつを使って行います。

とりあえずファイルをテキストファイル(これ超重要)として開きます。
ファイルは開かないと何も始まりません。

テキストファイルを開くには、基本的にOpenTextFile()関数を使用します。(他にもありますが使い勝手が悪い)

var fs = new ActiveXObject("Scripting.FileSystemObject");
var file = fs.OpenTextFile("開くテキストファイルのパス");

このときOpenTextFile関数が返した値(ここではfile変数)で開いたファイルに対して様々な操作を行なえるようになります。

また、開いたファイルは用が済んだら閉じましょう。

file.Close();

/* ここからは任意 */
//解放
fs = null;
file = null;

テキストファイルを1行読み込む(1行読み込み)


1行だけ読み込むにはReadLine()関数を使用します。
/*
  あらかじめテキストファイルを開いておく
  var fs = new ActiveXObject("Scripting.FileSystemObject");
  var file = fs.OpenTextFile("開くテキストファイルのパス");
*/

/* 1行目のみ読み込む */
text[0] = file.ReadLine();

/* 2行目を読み込む */
text[1] = file.ReadLine();
ReadLine関数は、呼び出すたびに1行ずつ読み込みますので大変便利です。

テキストファイルを文字数を指定して読み込む


文字数を指定して読み込むには、Read()関数を使用します。
/*
  あらかじめテキストファイルを開いておく
  var fs = new ActiveXObject("Scripting.FileSystemObject");
  var file = fs.OpenTextFile("開くテキストファイルのパス");
*/

/* ファイルの先頭から6文字読み込む */
text = file.Read(6);

テキストファイルをすべて読み込む


テキストファイルをまとめて読み込むには、ReadAll()関数を使用します。
/*
  あらかじめテキストファイルを開いておく
  var fs = new ActiveXObject("Scripting.FileSystemObject");
  var file = fs.OpenTextFile("開くテキストファイルのパス");
*/

/* テキストファイルをすべて読み込む */
text = file.ReadAll();
ReadAll()関数は便利ですが、メモリを多く消費します。ですので極力使わず、ReadLine()関数をうまく使うようにしましょう。
var text = "";
/* ファイルが最後まで読み込まれるまでループ */
while (!file.AtEndOfStream){
  text += file.ReadLine();
}
AtEndOfStreamプロパティにはテキストファイルが終端に達しているかを示す真偽値が入っています。終端ならtrue、そうでなければfalseです。
他にも似たようなプロパティAtEndOfLineがありますが、これは空行に到達すると終端に達していないにも関わらずtrueになってしまいます。よってここでAtEndOfLineを使うと、空行混じりのファイルが読み込めなくなります。AtEndOfStreamを使うようにしましょう。

いかがだったでしょうか。意外と簡単だったと思います。Scripting.FileSystemObjectではファイルへの書き込みや追記も可能です。次回(あれば)はテキストファイルへの書き込みのお話をしたいと思います。

注意
今回使用したScripting.FileSystemObjectは、ActiveXコントロールを必要とします。ActiveXコントロールはHTAなどのセキュリティレベルの低い状態のIEまたはデジタル署名ずみのコンテンツをIEで動作させるときのみ使用できます。一般的なWebページを作成する際は、FileAPIなどを使うようにしてください。
また、私が作ったサンプルに著作権なんてあるわけがありません。ご自由に転載・引用・二次配布などしていただいて構いません。ただし、それらのサンプルでエラーが起こったり、データが消えたり、マシンが火を吹いたとしても私(chiko ryo)は一切の責任を負いませんのでご注意ください。

2015年9月27日日曜日

「Javascriptで方向幕再現」の作り方

お久しぶりです、chiko ryoです。

今回は、以前お約束した「209系方向幕をJavaScriptで作る」 の解説です。

では、いきなりですがソースを貼ります。

function myMaku(){
         var Y = eval(document.makuform.zahyo.value);
         if(Y < 0 || Y > 44){            // 44の部分は対応番号が何番まであるかで調整ください。
          alert("0~44までの適正な値を入力してください。");
          return false;
         }
         // 移動先の座標を取得
         Yfor = eval("document.makuform.s" + String(Y) + ".value");
         // スタート地点の座標を取得
         Yfrom = document.getElementById("maku").contentWindow.document.body.scrollTop;
         // 幕を動かすスピードを取得
         Ys = eval(document.makuform.speed.value) / 1000;
         // 上に行くのか下に行くのか?
         if(Yfor < Yfrom){   // Y座標を小さくしていく
          Ys = (-1) * Ys;    // -1を掛けて正負を逆転する
          my_parse = false;
         }else if(Yfor > Yfrom){
          my_parse = true;
         }else{              // 移動は不要
          return false;
         }
         makuI = Yfrom;
         myMakuReturn = setInterval("myMakucore()", 1);
         return false;
         
}

function myMakucore(){
 if(Ys > 0 && makuI > Yfor){   // Y座標が増えていって、オーバーした
  document.getElementById("maku").contentWindow.document.body.scrollTop = Yfor;
  clearInterval(myMakuReturn);
  return;
 }else if(Ys < 0 && makuI < Yfor){ // Y座標が減っていって、オーバーした
  document.getElementById("maku").contentWindow.document.body.scrollTop = Yfor;
  clearInterval(myMakuReturn);
  return;
 }else if(makuI == Yfor){
  clearInterval(myMakuReturn);
  return;
 }else{
  makuI = makuI + Ys;
  document.getElementById("maku").contentWindow.document.body.scrollTop = makuI;
 }
}

<form name="makuform" onSubmit="return myMaku();"><div class="box" id="box">
<iframe src="209gazo.html" id="maku"></iframe>
</div><br>
幕対応番号を入力: 
<input type="text" name="zahyo" value="" /><br />
幕を動かすスピードを選択: 
<input type="range" name="speed" min="1" max="300" step="1" value="150" />
<input type="submit" name="go" value=" 実行 " /></p>
<p>幕対応表<br /><br />
<table border="1">
<tr>
<td>0<input type="hidden" name="s0" value="0" /></td><td>これ以上巻くな</td></tr>
<tr><td>1<input type="hidden" name="s1" value="135" /></td><td>試運転</td></tr>
<tr><td>2<input type="hidden" name="s2" value="280" /></td><td>回送</td></tr>
<tr><td>3<input type="hidden" name="s3" value="435" /></td><td>臨時</td></tr>
<tr><td>4<input type="hidden" name="s4" value="590" /></td><td>京浜東北線</td></tr>
<tr><td>5<input type="hidden" name="s5" value="748" /></td><td>品川</td></tr>
<tr><td>6<input type="hidden" name="s6" value="900" /></td><td>大崎</td></tr>
<tr><td>7<input type="hidden" name="s7" value="1050" /></td><td>田町</td></tr>
<tr><td>8<input type="hidden" name="s8" value="1200" /></td><td>池袋</td></tr>
<tr><td>9<input type="hidden" name="s9" value="1350" /></td><td>山手線</td></tr>
<tr><td>10<input type="hidden" name="s10" value="1500" /></td><td>田端</td></tr>
<tr><td>11<input type="hidden" name="s11" value="1650" /></td><td>上野</td></tr>
<tr><td>12<input type="hidden" name="s12" value="1800" /></td><td>快速上野</td></tr>
<tr><td>13<input type="hidden" name="s13" value="1960" /></td><td>赤羽</td></tr>
<tr><td>14<input type="hidden" name="s14" value="2100" /></td><td>快速赤羽</td></tr>
<tr><td>15<input type="hidden" name="s15" value="2260" /></td><td>大宮</td></tr>
<tr><td>16<input type="hidden" name="s16" value="2410" /></td><td>快速大宮</td></tr>
<tr><td>17<input type="hidden" name="s17" value="2550" /></td><td>蒲田</td></tr>
<tr><td>18<input type="hidden" name="s18" value="2700" /></td><td>快速蒲田</td></tr>
<tr><td>19<input type="hidden" name="s19" value="2850" /></td><td>鶴見</td></tr>
<tr><td>20<input type="hidden" name="s20" value="3000" /></td><td>快速鶴見</td></tr>
<tr><td>21<input type="hidden" name="s21" value="3150" /></td><td>磯子</td></tr>
<tr><td>22<input type="hidden" name="s22" value="3300" /></td><td>快速磯子</td></tr>
<tr><td>23<input type="hidden" name="s23" value="3455" /></td><td>南浦和</td></tr>
<tr><td>24<input type="hidden" name="s24" value="3603" /></td><td>快速南浦和</td></tr>
<tr><td>25<input type="hidden" name="s25" value="3755" /></td><td>東十条</td></tr>
<tr><td>26<input type="hidden" name="s26" value="3903" /></td><td>快速東十条</td></tr>
<tr><td>27<input type="hidden" name="s27" value="4055" /></td><td>桜木町</td></tr>
<tr><td>28<input type="hidden" name="s28" value="4203" /></td><td>快速桜木町</td></tr>
<tr><td>29<input type="hidden" name="s29" value="4370" /></td><td>東神奈川</td></tr>
<tr><td>30<input type="hidden" name="s30" value="4515" /></td><td>快速東神奈川</td></tr>
<tr><td>31<input type="hidden" name="s31" value="4665" /></td><td>大船</td></tr>
<tr><td>32<input type="hidden" name="s32" value="4815" /></td><td>快速大船</td></tr>
<tr><td>33<input type="hidden" name="s33" value="4968" /></td><td>八王子</td></tr>
<tr><td>34<input type="hidden" name="s34" value="5118" /></td><td>快速八王子</td></tr>
<tr><td>35<input type="hidden" name="s35" value="5280" /></td><td>橋本</td></tr>
<tr><td>36<input type="hidden" name="s36" value="5425" /></td><td>快速橋本</td></tr>
<tr><td>37<input type="hidden" name="s37" value="5575" /></td><td>町田</td></tr>
<tr><td>38<input type="hidden" name="s38" value="5723" /></td><td>快速町田</td></tr>
<tr><td>39<input type="hidden" name="s39" value="5870" /></td><td>中山</td></tr>
<tr><td>40<input type="hidden" name="s40" value="6010" /></td><td>快速中山</td></tr>
<tr><td>41<input type="hidden" name="s41" value="6165" /></td><td>小机</td></tr>
<tr><td>42<input type="hidden" name="s42" value="6315" /></td><td>快速小机</td></tr>
<tr><td>43<input type="hidden" name="s43" value="6465" /></td><td>横浜線</td></tr>
<tr><td>44<input type="hidden" name="s44" value="8868" /></td><td>これ以上巻くな</td></tr>
</table>
</form>
</p>

.box{
height: 150px;
width: 400px;
padding: none;
overflow: auto;
border: none;
-webkit-overflow-scrolling: touch;
}

#maku{
display: block;
width: 100%;
height: 100%;
border: none;
}

目がおかしくなった人、ごめんなさい。

では、軽く解説を。まずはmyMaku()からいきます。

var Y = eval(document.makuform.zahyo.value);
Yに幕対応番号を代入しています。eval()に渡しているのは数値に変換するためです。脆弱性とか気にしないww

if(Y < 0 || Y > 44){            // 44の部分は対応番号が何番まであるかで調整ください。
  alert("0~44までの適正な値を入力してください。");
  return false;
}
存在しない番号が入力された際のエラー対策です。

// 移動先の座標を取得
Yfor = eval("document.makuform.s" + String(Y) + ".value");
ここは少し難しいので解説します。
まずeval()の引数からみてみます。
"document.makuform.s" + String(Y) + ".value"
name属性値がmakuformであるform要素を取得しているのはわかりますよね?(そこまでは解説しません)
変数Yには、幕対応番号が数値型で代入されています。(2行目にeval()があります)
それをString()に渡していますので、文字列型に変換されます。
つまり、"s"と幕対応番号を文字列として連結して生成した文字列と同じname属性値を持つinput要素を取得しています。
例えば幕対応番号3の場合、
"document.makuform.s" + String(3) + ".value"
となり、document.makuform.s3.valueという文字列が生成されます。
それをeval()に渡してvalueを取得しているのです。

if(Yfor < Yfrom){   // Y座標を小さくしていく
Ys = (-1) * Ys;    // -1を掛けて正負を逆転する
    my_parse = false;
}else if(Yfor > Yfrom){
    my_parse = true;
}else{              // 移動は不要
    return false;
}
makuI = Yfrom;
myMakuReturn = setInterval("myMakucore()", 1);
return false;
if文で幕が上へ行くべきか下へ行くべきかを判断させます。
現状のscrollTopよりも行先のscrollTopのほうが小さい場合はscrollTopを減らしていく必要があります。
実際にscrollTopの改変をしている41行目では加算をしています。
「ある実数(makuI)にもう一つの実数(Ys)を足すと、元の実数(makuI)が小さくなった」 という動作が要求されますので、Ysを負の数にしましょう。そこで(-1)を掛け算します。
正の数 * 負の数 = 負の数です。正の数 + 負の数 は元の数より小さくなります。

ここで解説は以上です。ここまでついてこられた方であれば難なく理解いただけると思います。

どのブログサービスを使うべきか

世の中には、多くのブログサービスがあります。

  • アメーバブログ(アメブロ)
  • Yahoo!ブログ
  • Blogger(このブログはBloggerです)
  • WordPress
  • 楽天ブログ
etc...

これだけあると、初心者はどうすればいいかわからなくなってしまいます。

そこで、それぞれの長所や短所をまとめました。


アメーバブログ


もっとも人気のあるといって過言でないブログサービスです。また、簡単な操作が可能です。
著名人など多くの人が利用しており、アメーバのアカウントを作ると勝手にブログは作成されます。
あいさつペタなどの特徴的な機能のほか、アカウントが非常に多いために友達もできると評判です。

しかし、カスタマイズ性に欠けるため、JavascriptやCSSなどをゴリゴリ書きたいエンジニアさんや、カスタマイズを楽しみたい方は避けるべきです。


Yahoo!ブログ


比較的簡単にブログが作れると評判です。
Yahoo!アカウントとの連携ができるからといった理由などで評判はいいようです。
しかし、コメント投稿の際の画像認証が不要などの理由から、ロボットによる迷惑コメントが相次いでいます。セキュリティ面からみると、避けるべきかもしれません。
カスタマイズも思うようにできないようです。


Blogger


今私が使用しているサービスです。
Googleと共通のアカウントで運営できるため、Google+やYoutubeなどとの連携は最高です。
テンプレートも数多く用意されているほか、大半のHTMLやCSS、デザインや画面右側のガジェット(PC版のみ)が編集できます。
ただHTMLの自動補正機能が上級者にとっては邪魔になることがあるので、JavascriptやCSSは極力外部ファイル化するのがポイントです。
比較的初心者から上級者までおすすめできる内容です。


WordPress


比較的上級者向けです。
何よりもカスタマイズ性はこの上なく最高です。
数多くのプラグインが使用できるほか、なにせ管理者自ら構築したサーバーですので正直、何かやろうと思ったらなんでもできます。
SSL暗号化、独自ドメインなどはもちろん、FTP転送や同じドメイン内にファイルが設置できるためにいろいろとできます。
既定で設定されているCSSなどを取り払うこともPHPの知識があれば可能です。つまり、なにもかも思い通りになります。
ただし、セキュリティや脆弱性、PHP、プラグイン、サーバーやインターネット、SEOに関する専門知識が必要になります。徹底的に上級者向けを追及したサービスといえます。


まとめ

結果としての管理人のおすすめです。
  • 初心者ならBlogger
  • 上級者ならWordPress

長い記事にお付き合いいただきありがとうございました。

209系方向幕をJavascriptで作る

どうもこんにちは。

この間(随分前になりますが...)、 国鉄方向幕書体 をダウンロードしました。

そこで思いついたのが、Javascriptでの巻き取り機能をつける、ということです。

209系方向幕

JavaScriptでゴリゴリ書きました。
クロスドメインでセキュリティがあーだこーだ...という都合で、サンプルは外部サイトに設置しました。

そのうち作り方公開します...

路線も増やせたらいいなーと思っています。車種ごとの移植もそれほど苦ではないので。

ではまた、ご期待ください。

※これらのスクリプト、HTMLなどはすべて1から管理人が作成しています。そのためバグ等あるかもしれませんが、ご了承ください。またそういったものを発見された場合には、コメントにて報告にご協力ください。当ブログをより良いものとするため、ご協力お願いします。
ちなみに動作確認はIE9とGC7で行っています。

209系方向幕

遊び方

  1. ページ下半分に幕対応表があります。その表示したい行先の左側に表示されている数字を半角で入力してください。
  2. 「幕を動かすスピードを選択」の右側のスライダーは幕回しのスピード調整用です。左に行けば遅く、右に行けば速くなります。一番左はかなり遅いです。なお、幕を回し始めてから設定を変更しても、すぐには反映されません。その次に幕を回したとき、有効になります。
  3. 上の二つが調整できたら、「実行」ボタンをクリックします。幕が回り始めてから自動的に止まるまで、途中で止めることはできません。どうしてもという時は再読み込み願います...
  4. ちなみに幕表示部分の右のスクロールバーを操作すると手動で幕を巻くこともできます。ただし、自動で幕回しをしている最中はこの操作はできません。

209系方向幕

...では、思いっきりお楽しみください!!

Javascriptで郵便番号検索する

どうもこんにちは。必死で北斗星のはんだ付けを急いでしているchiko ryoです。

今回はよく通販サイトなどで見かける、「郵便番号で住所検索」についてです。

<script src="https://ajaxzip3.github.io/ajaxzip3.js" charset="UTF-8"></script>
<form>
郵便番号:
<input type="text" name="number1" size="4" maxlength="3"> - <input type="text" name="number2" size="5" maxlength="4"
onKeyUp="AjaxZip3.zip2addr('number1','number2','ken','shi','after');"><br>
都道府県: <input type="text" name="ken" size="40"><br>
市町村区: <input type="text" name="shi" size="40"><br>
以降の住所: <input type="text" name="after" size="40">
</form>

以上です。簡単ですね。

今回目新しいのはこれでしょうか。
onKeyUp="AjaxZip3.zip2addr('number1','number2','ken','shi','after');"

1行目で読み込んだライブラリで定義されている関数です。

書式は以下になります。

AjaxZip2.zip2addr( '〒上3桁', '〒下4桁', '都道府県', '市区町村', '町域大字', '丁目番地' );


引数にはinputタグのname属性を指定します。<form>タグのname属性は不要です。

今回はテキストフォームを使用していますが工夫次第でinnerHTMLなども使用可能です。

郵便番号のデータですが、常にデータベースは更新されるため、設置や管理も大変楽です。

実行例


郵便番号:
都道府県:
市町村区:
以降の住所:

パスワードの安全度チェックをする

いろいろなところで見かける「パスワードの安全度チェック」なるものをしてみます。

では、ソースコードを。

<script type="text/javascript" src="passwordchecker.js"></script>
<script type="text/javascript">
function myCheck(){
 var label = getPasswordLevel(document.pass.text.value);
 var dom = document.getElementById("check");

 if(label == 1) dom.innerHTML = "<span style='font-color: red;'>危険</span>";
 else if(label == 2) dom.innerHTML = "<span style='font-color: orange;'>やや危険</span>";
 else if(label == 3) dom.innerHTML = "<span style='font-color: #0088ff;'>普通</span>";
 else if(label == 4) dom.innerHTML = "<span style='font-color: #08f;'>やや安全</span>";
 else if(label == 5) dom.innerHTML = "<span style='font-color: #00f;'>安全</span>";
}
</script>

<!-- ここからは表示部分 -->
<form name="pass">
<input type="text" name="text" value="ここにパスワードを入力" onchange="myCheck()" />
</form><br />
<div id="check">ここに実行結果が表示されます。</div>

下のサイトからライブラリがダウンロードできます。
JavaScript パスワード強度判定ライブラリ「Password Checker」

辞書に載っている文字を含むパスワードや数字だけのパスワードは、容易に想像がつくため「弱い」判定が下る、大文字や記号、英数字などを混ぜると強度が増すなどの判断基準が用いられています。

そのライブラリでは、getPasswordLevel()という関数が定義されています。この関数にパスワードを渡すと、安全度が返ります。
1が返れば危険、2が返ればやや危険、...といった具合で、3が普通、5が安全です。(確証はないですが;;)

実行例

※データはサーバーには送信されませんが、念のため本物のパスワードは入力しないでください。

JavascriptでGoogle検索を行う

Google検索をすると、やけに長いアドレスに気付くと思います。

...そうです。Google検索はGET転送をしているのです。
通常POST転送をJavascriptで実現しようとすると、Ajaxなどを使うことになります。しかし、Google検索ではGET転送を採用しているため、Javascriptでの操作が容易になります。

では早速ソースコードを。

<form action="https://www.google.co.jp/search" method="get">
<input type="text" name="q" value="" />
<input type="submit" value=" 検索 " />
</form>

さて、、、解説は不要ですね!

ただしこれらの属性値を一つでも変更すると動かなくなるものもありますのでご注意くださいませ。

一応これで一通り完成ですが、Javascriptを使うと条件で絞って検索したり、動画検索・画像検索させたり、Ajaxを使って入力と同時に検索結果を表示する、なんてことも可能です。

改造の仕方によってはかなり高機能なものも作れます。
いろいろな検索をしてGET転送でどのように値が送信されているのかを研究してみてください。

実行例

参考:Yahoo検索

<form action="http://search.yahoo.co.jp/search" method="get" target="_blank">
<input type="text" name="p" />
<input type="hidden" name="fr" value="yssw" />
<input type="hidden" name="ei" value="UTF-8" />
<input type="submit" value=" 検索 " />
</form>

2015年4月11日土曜日

JavaScriptでINIファイルを解読する その2

前回のJavascriptでINIファイルを解読する その1でソースを公開したINIを解読するための関数「myReadInI()」。

その更新バージョンを作りましたので、またもソースを公開します。

function myReadInI(mySname, myPname, myFname){

var i = 0; // プロパティiとjはカウンタです。
var j = 0;
var t = null; // コメント除去に使用します。
var ts = 0;   // これもです。

// オブジェクト生成
var objFileSys = new ActiveXObject("Scripting.FileSystemObject");

var objTextStream = objFileSys.GetFile(myFname).OpenAsTextStream(1, 0);
/*読み込みモードを使用、文字コードはUnicodeです。(Unicode文字が扱えるようにするため)*/

var data = new Array(); // 空の配列

// ファイルが最後まで読み込まれるまでループ  読み込み
while (objTextStream.AtEndOfLine==false) {

   t = objTextStream.ReadLine();
   ts = t.indexOf(";"); // コメントを探す
   if(ts == -1){ // コメントがない
    data[i] = t;
   }else{ // コメントあり
    data[i] = t.substring(0, ts);
   }
   i++;
}

// 読み込み及びコメント除去 ここまで
// 解読 ここから

do{
 var my1 = data[j].indexOf("[" + mySname);
 j++;
}while(my1 == -1); // 一行ずつ検索し、該当するセクションを探す
j--;

// 指定のセクションの内容の始まる行数(0から)を退避
var mySstert = j + 1;

// セクションの終わりを探す(先ほど先頭が見つかった行の次からスタート)
j++;
do{
 var my2 = data[j].indexOf("[");
 j++;
}while(my2 == -1);
j--;

// 指定セクションの最後の行を退避
mySend = j - 1;

// パラメータ名を検索
var my3 = mySstert;
do{
 var my4 = data[my3].substring(0, data[my3].indexOf("="));
 my3++;
}while(my4 != myPname);
my3--;

// 抽出
var Returndata = data[my3].substring(data[my3].indexOf("=") + 1);

// 得られた値を返す
return Returndata;

} // function宣言終了

強調表示されている行が変更箇所です。
では解説を。

t = objTextStream.ReadLine();

ファイル読み込み部分ですが、前回と違いいきなりdata配列に代入せず、一旦変数tに代入しました。(もう少しそれらしい名前をつけてあげましょう(^ ^; )

ts = t.indexOf(";"); // コメントを探す
if(ts == -1){ // コメントがない
 data[i] = t;
}else{ // コメントあり
 data[i] = t.substring(0, ts);
}

はい、ここが一番前回と異なる点です。前回は最後にコメント除去をしていました。パラメータ名は=の左側と完全一致しているかで、引数で指定されたパラメータ名と一致しているかの判定していたため問題ありませんでした。しかし、セクション名はindexOf()で一行ずつ検索をかけていたため、セミコロンをつけても角カッコがセクション名として認識されていました。今回のバージョンアップでそれが改善された形となります。
indexOf()で;を検索し、もしも;が存在すればそこから右を削除します。そのあとにdata配列に代入しているのです。

当然、ファイル読み込み時にコメント除去処理をしたため、最後のコメント除去プログラムは削除しました。

※この関数はコールされるたびにファイルを読み込み直し、一行ずつコメント除去、セクション名およびパラメータ名の検索をします。PHPのmail()関数のように何度も呼び出すのは非常に非効率的であります。現在その欠点を解消した関数を開発中です、、、
今しばらくお待ちください。

[追記] 欠点を解消した関数が完成しました。詳しくは次回のJavascriptでINIファイルを解読する その3をご覧ください。

2015年4月1日水曜日

JavascriptでINIファイルを解読する その1

ちょっと気分を変えてプログラミングのお話を。

HTMLとJavascript、VBScriptなどでウィンドウアプリケーションが作れるという便利ツール

HTA

このHTAでINIファイルを読み込めればなぁ...と前々から思っていたのです。

そこで、さらっと書いてみたスクリプトがこれ。

function readInI (section, para) {
var i = 0;
var fs = WScript.CreateObject("Scripting.FileSystemObject");   // オブジェクト
var file = fs.OpenTextFile("text.ini", 1, false, -1);   // ファイルを開く

while (objTextStream.AtEndOfLine==false) {   // 空行が出現するまでループする
   var data[i] = file.ReadLine();   // 1行ずつ読み込む
   i++;

...下につづく

しかし、これだとエラーがでます。

「'WScript'は定義されていません」

どういうことかというと、WScriptオブジェクトはwscript.exeにしか使えないのです。要するに、HTAのJavascriptでは使えない。

ではどうするか。その答えはこれです。

// オブジェクト生成
var objFileSys = new ActiveXObject("Scripting.FileSystemObject");
var objTextStream = objFileSys.GetFile("test.ini").OpenAsTextStream(1, 0);

var data = new Array();

// ファイルが最後まで読み込まれるまでループ  読み込み
while (objTextStream.AtEndOfLine==false) {

   data[i] = objTextStream.ReadLine();
   i++;

}

...下につづく

これで正常にテキストファイルが読み込めるようになりました。

最終的なスクリプトを下に示します。


function myReadInI(mySname, myPname, myFname){

var i = 0;   // プロパティiとjはカウンタです。
var j = 0;

// オブジェクト生成
var objFileSys = new ActiveXObject("Scripting.FileSystemObject");
var objTextStream = objFileSys.GetFile(myFname).OpenAsTextStream(1, 0);
/*読み込みモードを使用、文字コードはUnicodeです。(Unicode文字が扱えるようにするため)*/

var data = new Array();   // 空の配列

// ファイルが最後まで読み込まれるまでループ  読み込み
while (objTextStream.AtEndOfLine==false) {
   data[i] = objTextStream.ReadLine();
   i++;
}

// 読み込み ここまで
// 解読 ここから

do{
 var my1 = data[j].indexOf("[" + mySname);
 j++;
}while(my1 == -1);   // 一行ずつ検索し、該当するセクションを探す
j--;

// 指定のセクションの内容の始まる行数(0から)を退避
var mySstert = j + 1;

// セクションの終わりを探す(先ほど先頭が見つかった行の次からスタート)
j++;
do{
 var my2 = data[j].indexOf("[");
 j++;
}while(my2 == -1);
j--;

// 指定セクションの最後の行を退避
mySend = j - 1;

// パラメータ名を検索
var my4 = mySstert;
do{
 var my6 = data[my4].substring(0, data[my4].indexOf("="));
 my4++;
}while(my6 != myPname);
my4--;

// コメント除去
var my3 = data[my4].indexOf(";");
if(my3 != -1){
 data[my4] = data[my4].slice(0, my3);
}

// 抽出
var Returndata = data[my4].substring(data[my4].indexOf("=") + 1);

// 得られた値を返す
return Returndata;

}   // function宣言終了

ソースをダブルクリックすると全選択ができます。もちろん普通に選択することも可能です。解説はスクリプト内のコメントで十分でしょう。


書式  :  myReadInI( セクション名,  パラメータ名, テキストファイルのパス );

戻り値  :  取得したパラメータの値が返ります。※半角数字は文字で返りますので数値を読み込みたいときはeval()を使ってください。

パラメータ

第1引数 必須
 セクションの名前です。[ ](角カッコ)は含みません。

第2引数 必須
 INIファイルのパラメータの名前です。

第3引数 必須
 INIファイルまでのパスです。絶対・相対どちらも指定可です。拡張子はなんでもかまいませんが、テキストファイルでかつ下に示す文法に従う、UTF-8のデータでなければなりません。


この関数で読み込めるINIファイルの文法を以下に示します。

  1. セクション名の前には空白文字を入れてもかまいません。
  2. コメントは;(セミコロン)から行末までで、途中からコメントとしても大丈夫です。
  3. 空行から先はすべてコメントです。そうしたくない場合は、その行を ; でコメントとしてください。
  4. 最後の行には必ず [ が含まれている必要があります。
  5. セクション名およびパラメータ名は@などの特殊文字で囲むことを推奨します。これは、先頭が一致する名前だと行を誤認識してしまうことがあるためです。(そのうち修正します)
5.の例
INIファイルの内容

[test]
userid=ユーザーID
user=ユーザー
[end]
このINIファイルに対して
myReadInI("test", "user", "test.ini");
とすると、3行目のuserよりも先に2行目のuseridにindexOfがヒットしてしまうためです。

使用例




Downlordボタンをクリックするとサンプルプログラムがダウンロードされます。セキュリティが不安な方はソースをみて安心してくださいな。また展開してからtest.iniを作成してください。「ファイルが見つかりません」エラーがでます。

次回のJavascriptでINIファイルを解読する その2に続きます。