ローカルストレージの力! ― 2015年10月05日 23:19

ローカルストレージの力!


これは便利だ。

いちいちパラメーターを入れ直すことなく、立ち上げると、前回のデータがたちどころにロードされて計算してくれる。

(コピペの力!)
http://kfujito2.asablo.jp/blog/2015/10/04/7826051

多少手を入れたとはいえ、コードの中身については殆ど分からないまま、コピペだけでウェッブアプリケーション(未接続でも使えます)が使用できる!。

今日は、安全率の実装に取り組んでいるが、深度と安全率を組み合わせて、検討会資料(別添資料4)の適用を実現しようとしている(ほぼ、近い値が出ています)。

酸素減圧のところはまだ途中。

もちろん、この表では、酸素といっても、おそらく20パーセントの窒素を設定していると思われる(マスクからの漏れ想定)。

この20パーセントの所は、コードの中に直に書き込んでいる。

パラメーターとして、外出ししたいところだ。

最終減圧停止深度を変更(3m、6m、9m)にする仕掛けも作ってみた。

「停止+浮上」セクションにしか書いていない。

初回減圧停止のところで、最終減圧停止深度以下の値が出た時の回避策は取っていない(気にしない、気にしない・・・)。

今後の課題であるな。

実は、もう一つ課題があって、繰り返し潜水に対応するというものだ。

検討会報告の事例では、繰り返し潜水がでてくるが、この突合ができていない。

浮上後、大気圧下でガス抜きしているわけで、その計算をできるようにすればいいのだが、面倒くさい。

プロファイルとしては、水面で停止して、一定時間後に再度潜降してqn2なりqheを引き継ぐ形にすればいいだけだ。

潜降の計算の時には、初期値を変数(配列ではなく)で与えているので、そこを手直しする必要がある。

全体を見直さなければならなくなりそうなので、なかなか手を付けられない。

しかし、検討会報告書では、酸素減圧は、この2度目の潜水の値を使用しているので、ここを実装しないと、事例における酸素減圧の値と突合できない。

いくつか、課題は残っているが、ようやく先が見えてきた。

それにしても、ローカルストレージは使えるな。

もう、パラメーターだらけで、画面はこんなことになってる。

「アイテム一覧:
・保存するKey:(入力窓)
・保存する値:(入力窓)
・保存(ボタン)
・削除(ボタン)
<以下、表( )内は、注釈>
キー:値
・a1:1.21(安全率1)
・a2:1.40(安全率2)
・a3:1.35(安全率3)
・a4:1.10(安全率4)
・a5:1.10(安全率5)
・d:40(作業深度:m)
・d1:0(安全率適用深度係数:水面)
・d2:2(安全率適用深度係数:6m)
・d3:3(安全率適用深度係数:9m)
・d4:4(安全率適用深度係数:12~18m)
・nhe:0(ヘリウム濃度:割合)
・nn2:0.79(窒素濃度:割合)
・o2:12(酸素切り替え深度:m)
・pa:100(大気圧:kPa)
・pb:0(水面のゲージ圧:kPa)
・qhe:0(水面のヘリウム分圧:kPa)
・qn2:74.5207(水面の窒素分圧:kPa)
・r:8(浮上速度:m/分)
・r0:8(潜降速度:m/分)
・s:2(最終減圧停止深度:×3m)
・t1:125(作業時間:分:滞底時間-潜降時間)
<以上で、表終了>
・値を変更したら、このボタンを押して再計算!(ボタン)
<以下、減圧プラン>
21m,1min(同左)
18m,14min(同左)
15m,24min(同左)
12m,48min(52分:エアブレイク1回分?)
9m,45min(55分:エアブレイク2回分?)
6m,102min」(124分:エアブレイク4回分?)

減圧プランを、別添資料4と比較すると、上記の( )内のようになる。

21個ものパラメーターを仕込んでしまったが、これを毎回全部コードの中に書いたりしていたら、開発効率は激減する(まあ、左程変わりないという気もするがな)。

とにかく楽だ。

エアブレイクについては、実装するかどうかも含めて検討中。

25分80パーセント酸素で、5分間空気を吸うというのが報告書のパターンのようなので、何らかの判定をして、そのパターンを取り込めれば、それを書くことにする。

どのタイミングでエアブレイクを入れるかというのは、どうやら、酸素(80パーセント・エンリッチド・エア?)を吸い始めてから連続して(深度に関わらず)25分経った時点で、空気を5分間吸い、さらに連続して25分間酸素を吸い・・・、というパターンになっているようだ。

深度変更(浮上)の際も含めて、そういう計算をしているようだな。

以前にも書いたが、エアブレイクは、法的義務ではない。

運用で行っている対応だ。

高圧則にもないし、他の通達にも載っていない。

(改正高気圧作業安全衛生規則が施行されます)
http://www.mhlw.go.jp/stf/seisakunitsuite/bunya/0000071152.html

規制対象ではないが、検討会報告書本体の事例2の中に出てくる。

(高気圧作業安全衛生規則改正検討会報告書:PDFを参照:25ページ)
http://www.mhlw.go.jp/stf/shingi/0000037880.html

「2.空気呼吸・酸素減圧
前述、2 回目の作業で、30[kPa]の深度から酸素減圧を行った場合について計算する。」

「酸素減圧は 25[min]酸素呼吸、5[min]空気呼吸を繰り返すため、25[min]間は窒素ガス濃度を 20[%]、5[min]間は79[%]として計算する。」

まあ、気が向いたらやるかな。

一応、現在のソースコードを最後に載せる。

「<html lang="ja">
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body onload="viewStorage();">



<script type="text/javascript">



/*
// (1)Web Storageの実装確認
if (typeof localStorage === 'undefined') {
window.alert("このブラウザはlocalStorage機能が実装されていません");
} else {
window.alert("このブラウザはlocalStorage機能を実装しています");
}
*/
var storage = window.localStorage;

// (2)localStorageへの格納
function setlocalStorage() {

var key = document.getElementById("textkey").value;
var value = document.getElementById("textdata").value;

// 値の入力チェック
if (key && value) {
window.localStorage.setItem(key, value);
}

key = "";
value = "";

viewStorage();
}

// (3)localStorageからのデータの取得と表示
function viewStorage() {

var list = document.getElementById("list")
while (list.firstChild) list.removeChild(list.firstChild);

// localStorageすべての情報の取得
for (var i=0; i < storage.length; i++) {
var _key = storage.key(i);

// localStorageのキーと値を表示
var tr = document.createElement("tr");
var td1 = document.createElement("td");
var td2 = document.createElement("td");
list.appendChild(tr);
tr.appendChild(td1);
tr.appendChild(td2);
td1.innerHTML = _key;
td2.innerHTML = storage.getItem(_key);
}
}

// (4)localStorageから削除
function removeStorage() {
var key = document.getElementById("textkey").value;
storage.removeItem(key);
key = "";
viewStorage();
}
/*
// (5)localStorageからすべて削除
function removeallStorage() {
storage.clear();
viewStorage();
}
*/

</script>


<section id="main">
保存するKey:<input id="textkey" type="text" />
保存する値:<input id="textdata" type="text" />
<button id="button" onclick="setlocalStorage()">保存</button>
<button id="button" onclick="removeStorage()">削除</button>
<!--
<button id="button" onclick="removeallStorage()">全て削除</button>
-->
<table border="1">
<tr>
<th>キー</th><th>値</th>
</tr>
<tbody id="list">
</tbody>
</table>

<input type="button" value="値を変更したら、このボタンを押して再計算!" onclick="location.reload();" />

</section>


<script type="text/javascript">
function print(str){
document.write(str + "<br />");
}

var a1=parseFloat(storage.getItem("a1"));//安全率1
var a2=parseFloat(storage.getItem("a2"));//安全率2
var a3=parseFloat(storage.getItem("a3"));//安全率3
var a4=parseFloat(storage.getItem("a4"));//安全率4
var a5=parseFloat(storage.getItem("a5"));//安全率5
var d=parseFloat(storage.getItem("d"));//作業深度(m)
var d1=parseFloat(storage.getItem("d1"));//安全率適用深度係数:水面
var d2=parseFloat(storage.getItem("d2"));//安全率適用深度係数:6m
var d3=parseFloat(storage.getItem("d3"));//安全率適用深度係数:9m
var d4=parseFloat(storage.getItem("d4"));//安全率適用深度係数:12~18m
var nhe=parseFloat(storage.getItem("nhe"));//ヘリウム濃度:割合
var nn2=parseFloat(storage.getItem("nn2"));//窒素濃度:割合
var o2=parseFloat(storage.getItem("o2"));//酸素切り替え深度:m
var pa=parseFloat(storage.getItem("pa"));//大気圧:kPa
var pb=parseFloat(storage.getItem("pb"));//水面のゲージ圧:kPa
var qhe=parseFloat(storage.getItem("qhe"));//水面のヘリウム分圧:kPa
var qn2=parseFloat(storage.getItem("qn2"));//水面の窒素分圧:kPa
var r=parseFloat(storage.getItem("r"));//浮上速度:m/分
var r0=parseFloat(storage.getItem("r0"));//潜降速度:m/分
var s=parseFloat(storage.getItem("s"));//最終減圧停止深度:÷3m
var t1=parseFloat(storage.getItem("t1"));//作業時間:分:滞底時間-潜降時間


//ここから開始
/*
<<<<潜降>>>>
*/

r0 = 10*r0;//潜降速度の返還(kPa)
var t = 10*d/r0;//潜降時間の計算

//半飽和時間の取り込み
var half_time_n2=[5,8,12.5,18.5,27,38.3,54.3,77,109,146,187,239,305,390,498,635];
var half_time_he=[1.887,3.019,4.717,6.981,10.189,14.453,20.491,29.057,41.132,55.094,70.566,90.189,115.094,147.170,187.925,239.623]

//酸素潜水の切り分け
if (o2 !== 0 && d <= o2){
nn2 = 0.2;
nhe = 0;
}

 //窒素計算
var kn2=new Array(15);
var bunatu_n2=new Array(15);

for (var i = 0; i < 16;i++){
kn2[i] = Math.log(2)/half_time_n2[i];
bunatu_n2[i] = (pa+pb)*nn2+r0*nn2*(t-1/kn2[i])-((pa+pb)*nn2-qn2-r0*nn2/kn2[i])*Math.exp(-kn2[i]*t);
}

//ヘリウム計算
var khe=new Array(15);
var bunatu_he=new Array(15);

for (var i = 0; i < 16;i++){
khe[i] = Math.log(2)/half_time_he[i];

bunatu_he[i] = (pa+pb)*nhe+r0*nhe*(t-1/khe[i])-((pa+pb)*nhe-qhe-r0*nhe/khe[i])*Math.exp(-khe[i]*t);
}

/*
<<<<作業>>>>
*/

//酸素潜水の切り分け
if (o2 !== 0 && d <= o2){
nn2 = 0.2;
nhe = 0;
}

var pb = 10*d;//作業深度でのゲージの圧計算
var qn2=new Array(15);
var qhe=new Array(15);

for (var i = 0; i < 16;i++){

//窒素計算
qn2[i] = bunatu_n2[i];
bunatu_n2[i] = (pa+pb)*nn2-((pa+pb)*nn2-qn2[i])*Math.exp(-kn2[i]*t1);

//ヘリウム計算
qhe[i] = bunatu_he[i];
bunatu_he[i] = (pa+pb)*nhe-((pa+pb)*nhe-qhe[i])*Math.exp(-khe[i]*t1);
}

/*
<<<<浮上開始時の分圧>>>>
*/

//窒素分圧の保存
var btm_bunatu_n2=new Array(15);
for (var i = 0; i < 16;i++){
btm_bunatu_n2[i] = bunatu_n2[i]
}

//ヘリウム分圧の保存
var btm_bunatu_he=new Array(15);
for (var i = 0; i < 16;i++){
btm_bunatu_he[i] = bunatu_he[i]
}

/*
<<<<M値>>>>
*/

//窒素係数の取り込み
var mvn2a=[126.885,109.185,94.381,82.446,73.918,63.153,56.483,51.133,48.246,43.709,40.774,38.68,34.463,33.161,30.765,29.284];
var mvn2b=[0.5578,0.6514,0.7222,0.7825,0.8126,0.8434,0.8693,0.891,0.9092,0.9222,0.9319,0.9403,0.9477,0.9544,0.9602,0.9653];

//ヘリウム係数の取り込み
var mvhea=[174.247,147.866,127.477,112.400,99.588,89.446,80.059,71.709,66.285,62.049,59.152,58.029,57.586,58.143,57.652,57.208]
var mvheb=[0.4770,0.5747,0.6527,0.7223,0.7582,0.7957,0.8279,0.8553,0.8757,0.8903,0.8997,0.9073,0.9122,0.9171,0.9217,0.9267]

/*
<<<<初回減圧停止深度の決定>>>>
*/

r = -10*r;//浮上速度(マイナス値への変換)
var hantei=new Array(15);
var mv=new Array(15);
var j = 0;//水面からの深度の係数(×3で深度)
while (j < 20){

var t = Math.abs((d-3*j)*10/r);//浮上時間の計算(絶対値)
var pc = 3*j*10;//浮上深度でのゲージ圧計算
for (var i = 0; i < 16;i++){

//窒素の計算
qn2[i] = btm_bunatu_n2[i];
bunatu_n2[i] = (pa+pb)*nn2+r*nn2*(t-1/kn2[i])-((pa+pb)*nn2-qn2[i]-r*nn2/kn2[i])*Math.exp(-kn2[i]*t);

//ヘリウムの計算
qhe[i] = btm_bunatu_he[i];
bunatu_he[i] = (pa+pb)*nhe+r*nhe*(t-1/khe[i])-((pa+pb)*nhe-qhe[i]-r*nhe/khe[i])*Math.exp(-khe[i]*t);

//M値の計算
mv[i]=(pa+pc)/((mvn2b[i]*bunatu_n2[i]+mvheb[i]*bunatu_he[i])/(bunatu_n2[i]+bunatu_he[i]))+((mvn2a[i]*bunatu_n2[i]+mvhea[i]*bunatu_he[i])/(bunatu_n2[i]+bunatu_he[i]));

//安全率の設定
var a;
if (pc === d1*30){//d1=0:水面を想定
a = a1;//1.21
} else if (pc === d2*30){//水面-2:6mを想定
a = a2;//1.4
} else if (pc === d3*30){//d3=3:9mを想定
a = a3;//1.35
} else if (pc >= d4*30 && pc <= (d4+2)*30){//12m-18mを想定
a = a4;//1.1
} else if (pc > (d4+2)*30){//18mより深い場合を想定
a = a5;//1.0
}

mv[i] = mv[i]/a;//安全率の適用

//浮上できるかどうかの判定(配列変数にフラグを設定)
if (bunatu_n2[i]+bunatu_he[i] > mv[i]){
hantei[i] = 1;
} else {
hantei[i] = 0;
}
}//for閉じ

//配列変数のフラグを合計
var hanteiti = 0;
for (var i = 0; i < 16;i++){
hanteiti = hanteiti+hantei[i];
}//for閉じ
if (hanteiti === 0){
break;
}
j++;//インクリメント
}//while閉じ

/*
<<<<停止+浮上>>>>
*/

if (j === 0){
print("end");
}

while (j > 0){//外側のwhile
var teisi = j;
var teisi_bunatu_n2=new Array(15);
var teisi_bunatu_he=new Array(15);

if (o2 !== 0 && j*3 <= o2){//酸素潜水の切り分け
nn2 = 0.2;
nhe = 0;
}


//停止分圧を変数に格納して保持
for (var i = 0; i < 16;i++){
teisi_bunatu_n2[i] = bunatu_n2[i];
teisi_bunatu_he[i] = bunatu_he[i];
}//for抜け

var pb = 3*teisi*10;//停止深度でのゲージ圧
var pc = 3*(teisi-1)*10;//浮上深度でのゲージ圧

//最終停止深度で浮上深度でのゲージ圧を水面に変更
if (j === 2 && s === 2){
pc = 0;
}else if(j === 3 && s === 3){
pc = 0;
}


var l = 1;//時間カウンターの初期値設定
while (l < 500){//内側のwhile

//停止の計算
var t = l;//1分毎に計算

for (var i = 0; i < 16;i++){

//窒素の計算
qn2[i] = teisi_bunatu_n2[i];
bunatu_n2[i] = (pa+pb)*nn2-((pa+pb)*nn2-qn2[i])*Math.exp(-kn2[i]*t);
qn2[i] = bunatu_n2[i];

//ヘリウムの計算
qhe[i] = teisi_bunatu_he[i];
bunatu_he[i] = (pa+pb)*nhe-((pa+pb)*nhe-qhe[i])*Math.exp(-khe[i]*t);
qhe[i] = bunatu_he[i];

}//for抜け

//浮上の計算

var t = Math.abs(3*10/r);//3m浮上する時間

//最終停止深度で水面までの浮上時間を変更
if (j === 2 && s === 2){
t = Math.abs(6*10/r);//6m浮上する時間
}else if(j === 3 && s === 3){
t = Math.abs(9*10/r);//9m浮上する時間
}

for (var i = 0; i < 16;i++){

//窒素の計算
bunatu_n2[i] = (pa+pb)*nn2+r*nn2*(t-1/kn2[i])-((pa+pb)*nn2-qn2[i]-r*nn2/kn2[i])*Math.exp(-kn2[i]*t);

//ヘリウムの計算
bunatu_he[i] = (pa+pb)*nhe+r*nhe*(t-1/khe[i])-((pa+pb)*nhe-qhe[i]-r*nhe/khe[i])*Math.exp(-khe[i]*t);

//M値の計算

//ヘリウム混合の時のM値
mv[i]=(pa+pc)/((mvn2b[i]*bunatu_n2[i]+mvheb[i]*bunatu_he[i])/(bunatu_n2[i]+bunatu_he[i]))+((mvn2a[i]*bunatu_n2[i]+mvhea[i]*bunatu_he[i])/(bunatu_n2[i]+bunatu_he[i]));

//安全率の設定
if (pc === d1*30){//d1=0:水面を想定
a = a1;//1.21
} else if (pc === d2*30){//水面-2:6mを想定
a = a2;//1.4
} else if (pc === d3*30){//d3=3:9mを想定
a = a3;//1.35
} else if (pc >= d4*30 && pc <= (d4+2)*30){//12m-18mを想定
a = a4;//1.1
} else if (pc > (d4+2)*30){//18mより深い場合を想定
a = a5;//1.0
}

mv[i] = mv[i]/a;//安全率の適用

//浮上できるかどうかの判定(配列変数にフラグを設定)
if (bunatu_n2[i]+bunatu_he[i] > mv[i]){
hantei[i] = 1;
} else {//if抜け
hantei[i] = 0;
}//else抜け
}//for抜け

//配列変数のフラグを合計
var hanteiti = 0;
for (var i = 0; i < 16;i++){
hanteiti = hanteiti+hantei[i];
}//for抜け

//浮上OKなら抜ける
if (hanteiti === 0){
break;
}//if抜け

l++;//変数「l」のインクリメント

}//内側のwhile抜け

//プリント表示
print(3*j+"m,"+ l +"min");

//最終停止深度で処理を抜ける
if (j === 2 && s === 2){
break;
}else if(j === 3 && s === 3){
break;
}

j--;//変数「j」のデクリメント

}//外側のwhile抜け

</script>
</body>
</html>
」