うしブログ

うしブログ

趣味で運営する、GeoGebraの専門ブログ。

(作業メモ)StartPoint要検証(2行の場合;テキスト変更時未定義問題)

(要修復)ToggleButton・RollPolygonWithoutSlipping・貯金時計・直感力トレーニング

On Update スクリプト内で「オブジェクト更新前の値」を参照する方法

設例

数値オブジェクトnを作成する。最小値1、最大値10、増分1に設定して、スライダーを作成する。

ブランクのテキストオブジェクトtext1 = ""を作成する。

いま、nのスライダーを動かす直前のnの値が、n_{previous}であったとする。そして、nのスライダーを動かした結果、nの値がn_{current}に更新されたとする。

当該更新を監視して、text1の値を以下のように設定する、nのOn Update スクリプトを作成しなさい。

"nの更新前の値は、n_{previous}でした。nの更新後の値は、n_{current}です。"

※ n_{previous}、n_{current}には、その時の具体的な数字(1,2,...,10)が入るようにせよ。

方法1

 数値オブジェクトpreviousを、以下の定義で作成する。

previous = n

そして、nのOn Update スクリプトに、以下を記述する。

SetValue[text1,"nの更新前の値は、"+previous+"でした。nの更新後の値は、"+n+"です。"]

(解説)

nに従属するオブジェクト(ここではprevious)を、nのOn Update スクリプト内で参照する場合には、当該従属オブジェクトの値は、更新前のnの値に基づいて計算された値が採用される*1。この方法は、この仕様を利用したものである。

方法2

グローバルJavaスクリプトとして、以下のスクリプトを記述する。

//グローバル変数:nの更新前の値を入れる用
var nPrevious = ggbApplet.getValue('n');

function updateText(){
  //nの更新後の値
  var nCurrent = ggbApplet.getValue('n');
  ggbApplet.setTextValue('text1', 'nの更新前の値は、'+nPrevious+'でした。nの更新後の値は、'+nCurrent+'です。');
  //nPreviousを最新の値に更新
  nPrevious = ggbApplet.getValue('n');
}

そして、nのOn Update スクリプトに、以下のJavaScriptを記述する。

updateText();

(解説)

関数updateText内で、setTextValue メソッドを、古い値のnPreviousを用いて実行する。それから、nPreviousを最新の値に更新する。この順序がポイントである。

true or false game

点をクリックして楽しもう。

遊び方は、あえてプレイヤーにお任せします。 

設計

あらかじめ作成したオブジェクトは、数値オブジェクトnumberのみで、その他のオブジェクトは、全てJavaScriptを通じて作成・削除・変更を制御しています。ただし、下記URLの音素材は、事前にアップロードしておきました。

https://www.geogebra.org/material/show/id/zzxwytqu

グローバルJavaスクリプト
//headNameを頭文字にもつ特定のタイプのオブジェクトname1, name3, name4が存在しているならば、配列[1,3,4]を返す。
function getExistingObjIndex(headName,objType){
  var allObjNames = ggbApplet.getAllObjectNames(objType);
  var targets =allObjNames.filter(function(item){
    if(item.indexOf(headName)!=-1) return true;
  });
  targets.map( function(value, index, array){
    array[index] = eval(value.substr(headName.length));
  });
  return targets;
}

//nameを名前に含む特定のタイプのオブジェクトを全て削除する。
function deleteExistingObj(headName,objType){
  var targets = getExistingObjIndex(headName,objType);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.deleteObject(headName+targets[k]);
  }
}

//indexごとに異なる数式によって、動的な色をセットする
function setSequenceDynamicColor(headName, objType, redScript, greenScript, blueScript, index){
  var targets = getExistingObjIndex(headName,objType);
  index = RegExp(index,'g');
  for(var k = 0; k < targets.length; k++){
    ggbApplet.evalCommand('SetDynamicColor['+headName+''+targets[k]+', '+redScript.replace(index,targets[k])+', '+greenScript.replace(index,targets[k])+', '+blueScript.replace(index,targets[k])+']');
  }
}

//GeoGebra Scriptをセットする。handlerは、'click'ならonClick、それ以外ならonUpdate
function setGgbScript(objName, handler, script){
  //オブジェクト存在確認
  var isexist = ggbApplet.exists(objName);
  if(isexist){
    var objType = ggbApplet.getObjectType(objName);
    var onwhat = (handler=='click') ? 'val' : 'onUpdate'; 
    var xmlText = '<element type=\"'+objType+'\" label=\"'+objName+'\"><ggbscript '+onwhat+'=\"'+script+'\"/></element>';
  ggbApplet.evalXML(xmlText);
  }
}

//indexごとに異なるスクリプトをセットする
function setSequenceGgbScript(headName, objType, handler, script, index){
  var targets = getExistingObjIndex(headName,objType);
  index = RegExp(index,'g');
  for(var k = 0; k < targets.length; k++){
    setGgbScript(headName+targets[k], handler, script.replace(index,targets[k]));
  }
}

//indexごとに異なるGeoGebra Commandを実行する。str command〔例:'POINTα=(α,0)'〕, str index〔例:'α'〕, int 実行回数
function evalSequenceCommand(command,index,time){
index = RegExp(index,'g');
  for(var k = 1; k<=time; k++){
    ggbApplet.evalCommand(command.replace(index,k));
  }
}

//指定した個数だけ自由な点POINT+kを作成
function makePOINTs(number){
  //半径はここで指定
  var radius = 4;
  //点を作成
  evalSequenceCommand('POINTα=CopyFreeObject[Rotate[(0,'+radius+'),2 π*α /'+number+']]', 'α', number);
}

//指定した個数だけBOOL+kを作成
function makeBOOLs(number){
  evalSequenceCommand('BOOLα=true', 'α', number);
}

//既存のすべてのFUNCのproductを足して、0ならfalse,それ以外ならtrue
function isFuncWell(){
  var result=0;
  var targets = getExistingObjIndex('FUNC','list');
  for(var k = 0; k<targets.length; k++)
  result += ggbApplet.getValue('Product[FUNC'+targets[k]+']');
  if(result==0){return false;}
  else{return true;}
}

//指定した個数だけFUNC+kを作成
function makeFUNCs(number){
  do {
    evalSequenceCommand('FUNCα=CopyFreeObject[Sequence[If[t==α,true,RandomElement[{true, false}]], t, 1, '+number+']]', 'α', number);
  } while (isFuncWell())
}

//以下、ボタン用の特殊関数

//既存のオブジェクトを削除
function deleteWorld(){
  deleteExistingObj('POINT','point');
  deleteExistingObj('BOOL','boolean');
  deleteExistingObj('FUNC','list');
  deleteExistingObj('SEG','segment');
}

//新たにオブジェクトを作成
function createWorld(){
  var number = ggbApplet.getValue('number');
  makePOINTs(number);
  makeBOOLs(number);
  makeFUNCs(number);
  //線分を作成
  for(var point1 =1; point1<number; point1++){
    for(var point2 = 2; point2<=number; point2++){
      if(point1!=point2){
        ggbApplet.evalCommand('SEG'+point1+'and'+point2+'=Segment[POINT'+point1+',POINT'+point2+']');
        ggbApplet.evalCommand('SetConditionToShowObject[SEG'+point1+'and'+point2+',BOOL'+point1+'==true&&BOOL'+point2+'==true]');
        ggbApplet.setFixed('SEG'+point1+'and'+point2, false, false);
      }
    }
  }
}

//スクリプトをセット
function setScript(){
  var targets = getExistingObjIndex('POINT','point');
  targets.map( function(value, index, array){
    array[index] = 'If[Element[FUNCα,'+value+']==true,SetValue[BOOL'+value+',¬BOOL'+value+']]';
  });
  var script = '';
  targets.map( function(value) {
    script += value+'\n';
  });
  script += 'PlaySound[false]\nPlaySound[&quot;#zzxwytqu&quot;]';
  setSequenceGgbScript('POINT', 'point', 'click', script, 'α');
}

//色をセット
function setColor(){
  setSequenceDynamicColor('POINT', 'point', 'If[BOOLα==true,1,0]', 'If[BOOLα==true,0,0]', 'If[BOOLα==true,1,0]', 'α');
}
new game ボタンのOn Click スクリプトJavaScript
//既存のオブジェクトを削除
deleteWorld();

//新たにオブジェクトを作成
createWorld();

//スクリプトをセット
setScript();

//色をセット
setColor();

 

以上

「頭文字+通し番号」のオブジェクトに対する一括操作に使えるJavaScript関数まとめ

作成

//str command〔例:'POINTα=(α,0)'〕, str index〔例:'α'〕, int 実行回数
function evalSequenceCommand(command,index,time){
  index = RegExp(index,'g');
  for(var k = 1; k<=time; k++){
    ggbApplet.evalCommand(command.replace(index,k));
  }

現在のオブジェクト作成状況の取得

 //headNameを頭文字にもつ特定のタイプのオブジェクトname1, name3, name4が存在しているならば、配列[1,3,4]を返す。
function getExistingObjIndex(headName,objType){
  var allObjNames = ggbApplet.getAllObjectNames(objType);
  var targets =allObjNames.filter(function(item){
    if(item.indexOf(headName)!=-1) return true;
  });
  targets.map( function(value, index, array){
    array[index] = eval(value.substr(headName.length));
  });
  return targets;
}

削除

 //headNameを頭文字にもつ特定のタイプのオブジェクトを全て削除する。
function deleteExistingObj(headName,objType){
  var targets = getExistingObjIndex(headName,objType);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.deleteObject(headName+targets[k]);
  }
}

スタイル編集

表示非表示

//headNameを頭文字にもつ特定のタイプのオブジェクトのvisibilityを編集する。
function setExistingObjVisible(headName, objType, bool){
  var targets = getExistingObjIndex(headName, objType);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.setVisible(headName+targets[k], bool);
  }
}

固定、選択許可

//headNameを頭文字にもつ特定のタイプのオブジェクトのfixを編集する。
function setExistingObjFixed(headName, objType, fixbool, selectbool){
  var targets = getExistingObjIndex(headName, objType);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.setFixed(headName+targets[k], fixbool, selectbool);
  }
}

レイヤー

//headNameを頭文字にもつ特定のタイプのオブジェクトのint layerを編集する。
function setExistingObjLayer(headName, objType, layer){
  var targets = getExistingObjIndex(headName, objType);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.setLayer(headName+targets[k], layer);
  }
}

動的な色

//indexごとに異なる数式によって、動的な色をセットする
function setSequenceDynamicColor(headName, objType, redScript, greenScript, blueScript, index){
  var targets = getExistingObjIndex(headName,objType);
  index = RegExp(index,'g');
  for(var k = 0; k < targets.length; k++){
    ggbApplet.evalCommand('SetDynamicColor['+headName+''+targets[k]+', '+redScript.replace(index,targets[k])+', '+greenScript.replace(index,targets[k])+', '+blueScript.replace(index,targets[k])+']');
  }
}

こちらも参照

【RGB, HSL, HSV対応】GeoGebraのオブジェクトに動的な色をセットするJavaScript関数 - うしブログ

ラベル

//headNameを頭文字にもつ特定のタイプのオブジェクトのラベルのvisibilityを編集する。
function setExistingLabelVisible(headName, objType, bool){
  var targets = getExistingObjIndex(headName, objType);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.setLabelVisible(headName+targets[k], bool);
  }
}

スクリプト編集

前提として定義すべき関数①

//handlerは、'click'ならonClick、それ以外ならonUpdate
function setGgbScript(objName, handler, script){
  //オブジェクト存在確認
  var isexist = ggbApplet.exists(objName);
  if(isexist){
    var objType = ggbApplet.getObjectType(objName);
    var onwhat = (handler=='click') ? 'val' : 'onUpdate';
    var xmlText = '<element type=\"'+objType+'\" label=\"'+objName+'\"><ggbscript '+onwhat+'=\"'+script+'\"/></element>';
    ggbApplet.evalXML(xmlText);
  }
}

前提として定義すべき関数②

//handlerは、'click'ならonClick、それ以外ならonUpdate
function setJavaScript(objName, handler, script){
  //オブジェクト存在確認
  var isexist = ggbApplet.exists(objName);
  if(isexist){
    var objType = ggbApplet.getObjectType(objName);
    var onwhat = (handler=='click') ? 'val' : 'onUpdate';
    var xmlText = '<element type=\"'+objType+'\" label=\"'+objName+'\"><javascript '+onwhat+'=\"'+script+'\"/></element>';
    ggbApplet.evalXML(xmlText);
  }

ggbスクリプトの編集(一括設定)

//indexごとに異なるスクリプトをセットする
function setSequenceGgbScript(headName, objType, handler, script, index){
  var targets = getExistingObjIndex(headName,objType);
  index = RegExp(index,'g');
  for(var k = 0; k < targets.length; k++){
    setGgbScript(headName+targets[k], handler, script.replace(index,targets[k]));
  }
}

JavaScriptの編集(一括設定)

//indexごとに異なるスクリプトをセットする
function setSequenceJavaScript(headName, objType, handler, script, index){
  var targets = getExistingObjIndex(headName,objType);
  index = RegExp(index,'g');
  for(var k = 0; k < targets.length; k++){
    setJavaScript(headName+targets[k], handler, script.replace(index,targets[k]));
  }
}

※変数script内での各種記号の書き方(xml エンティティ)

 

改行:「&#xa;」

(')シングルクオーテーション:「&apos;」

(")ダブルクオーテーション:「&quot;」

(&)アンパサンド:「&amp;」

(<) 小なり:「&lt;」

(>) 左大なり:「&gt;」