うしブログ

うしブログ

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

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

「納車ゲーム ver 1.1」のグローバルJavaScript

//グローバル変数
var savedXML;
var PreSelectingCarNum;

function ggbOnInit() {
  //オブジェクトクリック時の処理
  ggbApplet.registerClickListener("clickFunc");
}

function mCs(){
  //編集前のセル数
  var preCellNum = ggbApplet.getValue('preCellNum');
  //編集後のセル数
  var cellNum = ggbApplet.getValue('CellNum');
  //既存のcellを削除
  for (var i = 1; i <= preCellNum; i++) {
    ggbApplet.deleteObject('cell'+i);
  }
  //既存のS,G,copycarを削除、copycarのイベントリスナを解除
  deleteExistingObj('START');
  deleteExistingObj('GOAL');
  var copycars = getExistingObjIndex('copycar');
  for(var k = 0; k < copycars.length; k++){
    ggbApplet.unregisterObjectUpdateListener('copycar'+copycars[k]);
  }
  deleteExistingObj('copycar');
  //新たにcellを作成
  ggbApplet.evalCommand('Execute[Sequence[\"cell\"+t+\"=Element[CellList,\"+t+\"]\",t,1,CellNum]]');
  //cellのlayerを0に設定
  setExistingObjLayer('cell', 1);
}

//strで頭文字nameを指定。name1, name3, name4が存在しているならば、配列[1,3,4]を返す。
function getExistingObjIndex(name){
  var allObjNames = ggbApplet.getAllObjectNames();
  var targets =allObjNames.filter(function(item){
    if(item.indexOf(name)!=-1) return true;
  });
  targets.map( function(value, index, array){
    array[index] = eval(value.substr(name.length));
  });
  return targets;
}

//頭文字nameのオブジェクトを全て削除する。
function deleteExistingObj(name){
  var targets = getExistingObjIndex(name);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.deleteObject(name+targets[k]);
  }
}

//頭文字nameのオブジェクトのvisibilityを編集する。
function setExistingObjVisible(name, bool){
  var targets = getExistingObjIndex(name);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.setVisible(name+targets[k], bool);
  }
}

//頭文字nameのオブジェクトのfixを編集する。
function setExistingObjFixed(name, fixbool, selectbool){
  var targets = getExistingObjIndex(name);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.setFixed(name+targets[k], fixbool, selectbool);
  }
}

//頭文字nameのオブジェクトのint layerを編集する。
function setExistingObjLayer(name, layer){
  var targets = getExistingObjIndex(name);
  for(var k = 0; k < targets.length; k++){
    ggbApplet.setLayer(name+targets[k], layer);
  }
}

//頭文字nameであり、現在存在するものを、リストオブジェクトlistNameとして取得する
function getObjList(name, listName){
  var allObjNames = ggbApplet.getAllObjectNames();
  var targets =allObjNames.filter(function(item){
    if(item.indexOf(name)!=-1) return true;
  });
  var contents = targets.toString();
  ggbApplet.evalCommand(listName+' = {'+contents+'}');
}

//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);
  }
}

//図オブジェクトobjNameの隅1,2,4を、str 式expC1,2,4で表される点に設定する
function setImgCorner(objName, expC1,expC2,expC4){
//オブジェクト存在確認
  var isexist = ggbApplet.exists(objName);
  if(isexist){
    var xmlText = '<element type=\"image\" label=\"'+objName+'\"><startPoint number=\"0\" exp=\"'+expC1+'\"/><startPoint number=\"1\" exp=\"'+expC2+'\"/><startPoint number=\"2\" exp=\"'+expC4+'\"/></element>';
  ggbApplet.evalXML(xmlText);
  }
}

//objNameを、現在のcolornumに対応する色にsetColorする
function setColorByColornum(objName){
  var colornum = ggbApplet.getValue('colornum');
  var code = ggbApplet.getColor('button'+colornum);
  var red = parseInt(code.substring(1,3), 16);
  var green = parseInt(code.substring(3,5), 16);
  var blue = parseInt(code.substring(5,7), 16);
  ggbApplet.setColor(objName,red,green,blue);
}

//赤いsegが存在しているか否かを、ggbオブジェクトisRedExistsに代入する。赤い車のsegsにおけるindexを返す(なければ- 1を返す)。
function isRedExists(){
  var segs = getExistingObjIndex('seg');
  if(segs.length==0){ggbApplet.evalCommand('SetValue[isRedExists,false]');return -1;}

  for(var k = 0; k < segs.length; k++){
    var color = ggbApplet.getColor('seg'+segs[k]);
    if(color == '#B51A1F'){
      ggbApplet.evalCommand('SetValue[isRedExists,true]');
      return k;
    }
    else{
      ggbApplet.evalCommand('SetValue[isRedExists,false]');
    }
  }
  return -1;
}

function clickFunc(objName){
  //既存のsegのオブジェクト名を配列で取得
  var segs = getExistingObjIndex('seg');
  var carnum = (Math.max.apply(null, segs)==-Infinity)?1:Math.max.apply(null, segs)+1;

  //クリックされたオブジェクトのタイプを取得
  var clickedObjData = ggbApplet.getObjectType(objName);
  ggbApplet.setTextValue('clickedobjtype',clickedObjData);
  ggbApplet.setTextValue('clickedobjname',objName);

  //編集画面(edit==true)かつセルをクリックしたならば以下の処理を実行
  var edit = ggbApplet.getValue('edit');
  var isCell = objName.indexOf('cell') != -1;
  var makingCar = ggbApplet.getValue('makingCar');

  if(edit && isCell){
    ggbApplet.evalCommand('SetValue[makingCar,¬makingCar]');
    //開始セルクリック時
    if(!makingCar){
      ggbApplet.evalCommand('START'+carnum+'=CopyFreeObject[Centroid['+objName+']]');
      ggbApplet.setVisible('START'+carnum, false);
      ggbApplet.evalCommand('SetValue[alert,false]');
    }
    //終了セルクリック時
    else{
      ggbApplet.evalCommand('GOAL'+carnum+'=CopyFreeObject[Centroid['+objName+']]');
      ggbApplet.setVisible('GOAL'+carnum, false);
      ggbApplet.evalCommand('seg'+carnum+'=Segment[START'+carnum+',GOAL'+carnum+']');
      setColorByColornum('seg'+carnum);
      ggbApplet.setLayer('seg'+carnum, 1);
      ggbApplet.setFixed('seg'+carnum, false,false);
      ggbApplet.evalCommand('copycar'+carnum+'=CopyFreeObject[master'+ggbApplet.getValue('colornum')+']');
      ggbApplet.setLayer('copycar'+carnum, 5);
      ggbApplet.setFixed('copycar'+carnum, true,true);
      setImgCorner('copycar'+carnum, 'CopyFreeObject[Translate[Dilate[GOAL'+carnum+', (0.4 + Distance[GOAL'+carnum+', START'+carnum+']) / Distance[GOAL'+carnum+', START'+carnum+'], START'+carnum+'], Vector[0.4UnitVector[PerpendicularVector[Vector[START'+carnum+', GOAL'+carnum+']]]]]]', 'CopyFreeObject[Translate[Dilate[START'+carnum+', (0.4 + Distance[GOAL'+carnum+', START'+carnum+']) / Distance[GOAL'+carnum+', START'+carnum+'], GOAL'+carnum+'], Vector[-0.4UnitVector[PerpendicularVector[Vector[GOAL'+carnum+', START'+carnum+']]]]]]', 'CopyFreeObject[Translate[Dilate[GOAL'+carnum+', (0.4 + Distance[GOAL'+carnum+', START'+carnum+']) / Distance[GOAL'+carnum+', START'+carnum+'], START'+carnum+'], Vector[-0.4UnitVector[PerpendicularVector[Vector[START'+carnum+', GOAL'+carnum+']]]]]]');
      //G位置の形式検査
      if(ggbApplet.getValue('x(GOAL'+carnum+')==x(START'+carnum+') && y(GOAL'+carnum+')==y(START'+carnum+') || x(GOAL'+carnum+')!=x(START'+carnum+') && y(GOAL'+carnum+')!=y(START'+carnum+')')){
        ggbApplet.deleteObject('START'+carnum);
        ggbApplet.deleteObject('GOAL'+carnum);
        ggbApplet.setFixed('copycar'+carnum, false,true);
        ggbApplet.deleteObject('copycar'+carnum);
        carnum--;
      }
      else{
        for(var k = 0; k < segs.length; k++){
          ggbApplet.evalCommand('If[IsDefined[Intersect[seg'+carnum+',seg'+segs[k]+']]||START'+carnum+' == ClosestPoint[seg'+segs[k]+', START'+carnum+']||GOAL'+carnum+' == ClosestPoint[seg'+segs[k]+', GOAL'+carnum+']||START'+segs[k]+' == ClosestPoint[seg'+carnum+', START'+segs[k]+']||GOAL'+segs[k]+' == ClosestPoint[seg'+carnum+', GOAL'+segs[k]+'],Execute[{\"Delete[START'+segs[k]+']\",\"Delete[GOAL'+segs[k]+']\",\"SetFixed[copycar'+segs[k]+',false,true]\",\"Delete[copycar'+segs[k]+']\"}]]');
        }
        if(segs+1!=getExistingObjIndex('seg').length){carnum--;}
      }
      isRedExists();
      if(isRedExists()!=-1 && ggbApplet.getValue('colornum')==1){ggbApplet.evalCommand('SetValue[colornum,2]');}
      //セーブポイントを作成
      if(ggbApplet.getValue('edit')){savedXML = ggbApplet.getXML();}
    }
  }
  
  //編集画面(edit==true)かつmakingCar==falseのとき、既存のS,G,seg,copycarをクリックしたならば以下の処理を実行
  var isSPoint = clickedObjData == 'point' && objName.indexOf('START') != -1;
  var isGPoint = clickedObjData == 'point' && objName.indexOf('GOAL') != -1;
  var isseg = objName.indexOf('seg') != -1;
  var iscopycar = objName.indexOf('copycar') != -1;
  var makingCar =ggbApplet.getValue('makingCar');
    if(edit && isSPoint && !makingCar){
      ggbApplet.deleteObject('START'+objName.substr(5));
      ggbApplet.deleteObject('GOAL'+objName.substr(5));
      ggbApplet.evalCommand('SetValue[makingCar,false]');
    }
    if(edit && isGPoint && !makingCar){
      ggbApplet.deleteObject('START'+objName.substr(4));
      ggbApplet.deleteObject('GOAL'+objName.substr(4));
      ggbApplet.evalCommand('SetValue[makingCar,false]');
    }
    if(edit && isseg && !makingCar){
      ggbApplet.deleteObject('START'+objName.substr(3));
      ggbApplet.deleteObject('GOAL'+objName.substr(3));
      ggbApplet.deleteObject('seg'+objName.substr(3));
    }
    if(edit && iscopycar && !makingCar){
      ggbApplet.deleteObject('START'+objName.substr(7));
      ggbApplet.deleteObject('GOAL'+objName.substr(7));
      ggbApplet.deleteObject('seg'+objName.substr(7));
      ggbApplet.deleteObject('copycar'+objName.substr(7));
    }
    isRedExists();
}

//線分を構成しないSTARTを削除
function removeSTART(){
  //STARTのindexを配列で取得
  var STARTs = getExistingObjIndex('START');
  //segのindexを配列で取得
  var segs = getExistingObjIndex('seg');
  for(var k=0; k < STARTs.length; k++){
    if(segs.indexOf(STARTs[k]) == -1){
      ggbApplet.deleteObject('START'+STARTs[k]);
    }
  }
}

//現在存在する全てのsegについて、中点の可動域を表す線分range+nを作成し、リストオブジェクトrangesとして取得する
function makeRanges(){
  deleteExistingObj('listO');
  deleteExistingObj('listA');
  deleteExistingObj('listB');
  deleteExistingObj('SEGBeforeDilate');
  deleteExistingObj('SEGAfterDilate');
  deleteExistingObj('range');

  //editをfalseにしたときの動作
  if(!ggbApplet.getValue('edit') && isRedExists()!=-1){
    var segs = getExistingObjIndex('seg');
    for(var k=0; k < segs.length; k++){
      //全seg(walls含む)に対し、ClosestPoint[seg,START]を取得〔listO〕
      var listO = (k==isRedExists()) ? 'CopyFreeObject[Zip[ClosestPoint[s,START'+segs[k]+'],s,Join[cars,wallsforred]]]' : 'CopyFreeObject[Zip[ClosestPoint[s,START'+segs[k]+'],s,Join[cars,walls]]]';
      ggbApplet.evalCommand('listO'+segs[k]+'='+listO);
      //listOのうち、Ray[START,GOAL]上にあるもの(START自身を除く)のみを抽出〔listA〕
      var listA = 'CopyFreeObject[RemoveUndefined[Zip[If[t ≟ ClosestPoint[Ray[START'+segs[k]+',GOAL'+segs[k]+'], t ]&&t!=START'+segs[k]+', t,?],t,listO'+segs[k]+']]]';
      ggbApplet.evalCommand('listA'+segs[k]+'='+listA);
      //listOのうち、Ray[GOAL,START]上にあるもの(START自身を除く)のみを抽出〔listB〕
      var listB = 'CopyFreeObject[RemoveUndefined[Zip[If[t ≟ ClosestPoint[Ray[GOAL'+segs[k]+',START'+segs[k]+'], t ]&&t!=START'+segs[k]+', t,?],t,listO'+segs[k]+']]]';
      ggbApplet.evalCommand('listB'+segs[k]+'='+listB);
      //ClosestPoint[listA, GOAL1]〜ClosestPoint[listB, START1]の線分(長さlength、中点Midpoint)を、Midpointでlength-2 - segの長さ / lengthだけDilateしたもの:segの中点の可動域としての線分 range1, range2, ...
      //Dilate前の線分seg〔segBeforeDilate〕
      var segBeforeDilate = 'CopyFreeObject[Segment[ClosestPoint[listA'+segs[k]+', GOAL'+segs[k]+'],ClosestPoint[listB'+segs[k]+', START'+segs[k]+']]]';
      ggbApplet.evalCommand('SEGBeforeDilate'+segs[k]+'='+segBeforeDilate);
      //Dilate後の線分〔segAfterDilate〕
      var segAfterDilate = 'CopyFreeObject[Dilate[SEGBeforeDilate'+segs[k]+',(Length[SEGBeforeDilate'+segs[k]+'] - 2 - Distance[START'+segs[k]+',GOAL'+segs[k]+']) / Length[SEGBeforeDilate'+segs[k]+'],Midpoint[SEGBeforeDilate'+segs[k]+']]]';
      ggbApplet.evalCommand('SEGAfterDilate'+segs[k]+'='+segAfterDilate);
      //segAfterDilateを格子点のみのリストにする〔rangePoints〕
      var rangePoints = 'CopyFreeObject[Sequence[Point[SEGAfterDilate'+segs[k]+',k/(If[Length[SEGAfterDilate'+segs[k]+']==0,1,Length[SEGAfterDilate'+segs[k]+']])],k,0,Length[SEGAfterDilate'+segs[k]+']]]';
      ggbApplet.evalCommand('range'+segs[k]+'='+rangePoints);
    }
    getObjList('range', 'Ranges');

    setExistingObjVisible('listO', false);
    setExistingObjVisible('listA', false);
    setExistingObjVisible('listB', false);
    setExistingObjVisible('SEGBeforeDilate', false);
    setExistingObjVisible('SEGAfterDilate', false);
    setExistingObjVisible('range', false);

    ggbApplet.setVisible('Ranges', false);
  }
}

//range上の点CENTER+n、CENTER+nの変更リスナとしてのLISTENER+n、初期位置としてのORIGIN+nを作成
function makeCENTERs(){
  deleteExistingObj('CENTER');
  deleteExistingObj('LISTENER');
  ggbApplet.deleteObject('CenterList');
  ggbApplet.deleteObject('ListenerList');
  ggbApplet.deleteObject('CompareCenterListener');
  ggbApplet.deleteObject('precount');
  ggbApplet.deleteObject('count');
  ggbApplet.deleteObject('totalcount');
  ggbApplet.deleteObject('countText');

  //(ORIGINが存在している場合に限り)既存のcopycar,START,GOALの位置をORIGINにしたがって移動
  var copycars = getExistingObjIndex('copycar');
  if(getExistingObjIndex('ORIGIN')!=0){
    for(var k=0; k < copycars.length; k++){
    ggbApplet.evalCommand('SetValue[copycar'+copycars[k]+',Translate[copycar'+copycars[k]+',Vector[Midpoint[Corner[copycar'+copycars[k]+',1],Corner[copycar'+copycars[k]+',3]],ORIGIN'+copycars[k]+']]]');
    ggbApplet.setFixed('copycar'+copycars[k], true,true);
    setJavaScript('copycar'+copycars[k], 'update', ' ');
    ggbApplet.evalCommand('SetValue[START'+copycars[k]+',Dilate[Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]], (-0.4 + Distance[Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]], Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]]]) / Distance[Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]], Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]]], Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]]]]');
      ggbApplet.evalCommand('SetValue[GOAL'+copycars[k]+',Dilate[Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]], (-0.4 + Distance[Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]], Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]]]) / Distance[Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]], Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]]], Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]]]]');
    }
  }
  deleteExistingObj('ORIGIN');

  //editをfalseにしたときの動作
  if(!ggbApplet.getValue('edit') && isRedExists()!=-1){
    var segs = getExistingObjIndex('seg');
    for(var k=0; k < segs.length; k++){
      ggbApplet.evalCommand('CENTER'+segs[k]+'=Point[range'+segs[k]+']');
      ggbApplet.evalCommand('SetValue[CENTER'+segs[k]+',Midpoint[seg'+segs[k]+']]');
      ggbApplet.evalCommand('LISTENER'+segs[k]+'=CopyFreeObject[CENTER'+segs[k]+']');
      ggbApplet.evalCommand('ORIGIN'+segs[k]+'=CopyFreeObject[CENTER'+segs[k]+']');
    }
    setExistingObjVisible('CENTER',false);
    setExistingObjVisible('LISTENER',false);
    setExistingObjVisible('ORIGIN',false);
    getObjList('CENTER', 'CenterList');
    getObjList('LISTENER', 'ListenerList');
    ggbApplet.evalCommand('CompareCenterListener=Zip[s ≠ t, s, CenterList, t, ListenerList]');
    ggbApplet.evalCommand('precount=Sum[Zip[If[s, 1, 0], s, CompareCenterListener]]');
    ggbApplet.evalCommand('count=0');
    ggbApplet.evalCommand('totalcount=count+precount');
    ggbApplet.evalCommand('countText=Text[totalcount+\"\",(0.5,scale+1)]');
  }
}

//kのrangeを更新,k以外のCENTER、LISTENERの位置を再設定
function updateRange(k){
  //k以外のcopycarsの通し番号だけを配列で取得
  var copycars = getExistingObjIndex('copycar');
  var excNum = copycars.indexOf(k);
  copycars.splice(excNum, 1);
  var isRangeKExist = ggbApplet.exists('range'+k);

  //kのrangeのみ更新
  if(isRangeKExist && PreSelectingCarNum != k){
    var listO = (excNum==isRedExists()) ? 'CopyFreeObject[Zip[ClosestPoint[s,START'+k+'],s,Join[cars,wallsforred]]]' : 'CopyFreeObject[Zip[ClosestPoint[s,START'+k+'],s,Join[cars,walls]]]';
    ggbApplet.evalCommand('SetValue[listO'+k+','+listO+']');
    //listOのうち、Ray[START,GOAL]上にあるもの(START自身を除く)のみを抽出〔listA〕
    var listA = 'CopyFreeObject[RemoveUndefined[Zip[If[t ≟ ClosestPoint[Ray[START'+k+',GOAL'+k+'], t ]&&t!=START'+k+', t,?],t,listO'+k+']]]';
    ggbApplet.evalCommand('SetValue[listA'+k+','+listA+']');
    //listOのうち、Ray[GOAL,START]上にあるもの(START自身を除く)のみを抽出〔listB〕
    var listB = 'CopyFreeObject[RemoveUndefined[Zip[If[t ≟ ClosestPoint[Ray[GOAL'+k+',START'+k+'], t ]&&t!=START'+k+', t,?],t,listO'+k+']]]';
    ggbApplet.evalCommand('SetValue[listB'+k+','+listB+']');
    //ClosestPoint[listA, GOAL1]〜ClosestPoint[listB, START1]の線分(長さlength、中点Midpoint)を、Midpointでlength-2 - segの長さ / lengthだけDilateしたもの:segの中点の可動域としての線分 range1, range2, ...
    //Dilate前の線分seg〔segBeforeDilate〕
    var segBeforeDilate = 'CopyFreeObject[Segment[ClosestPoint[listA'+k+', GOAL'+k+'],ClosestPoint[listB'+k+', START'+k+']]]';
    ggbApplet.evalCommand('SEGBeforeDilate'+k+'='+segBeforeDilate);
    //Dilate後の線分〔segAfterDilate〕
    var segAfterDilate = 'CopyFreeObject[Dilate[SEGBeforeDilate'+k+',(Length[SEGBeforeDilate'+k+'] - 2 - Distance[START'+k+',GOAL'+k+']) / Length[SEGBeforeDilate'+k+'],Midpoint[SEGBeforeDilate'+k+']]]';
    ggbApplet.evalCommand('SEGAfterDilate'+k+'='+segAfterDilate);
    //segAfterDilateを格子点のみのリストにする〔rangePoints〕
    var rangePoints = 'CopyFreeObject[Sequence[Point[SEGAfterDilate'+k+',k/(If[Length[SEGAfterDilate'+k+']==0,1,Length[SEGAfterDilate'+k+']])],k,0,Length[SEGAfterDilate'+k+']]]';
    ggbApplet.evalCommand('SetValue[range'+k+','+rangePoints+']');
  PreSelectingCarNum = k;
  }

  for(var k=0; k < copycars.length; k++){
    if(isRangeKExist){
      //CENTERの位置を再設定
      var scriptText1  = 'SetValue[CENTER'+copycars[k]+',Midpoint[Corner[copycar'+copycars[k]+',1],Corner[copycar'+copycars[k]+',3]]]';
      //LISTENERの位置を再設定
      var scriptText2  = 'If[LISTENER'+copycars[k]+'!=CENTER'+copycars[k]+',SetValue[count,count+1]]'
      var scriptText3  = 'SetValue[LISTENER'+copycars[k]+',CENTER'+copycars[k]+']';

      ggbApplet.setTextValue('scriptText1',scriptText1);
      ggbApplet.setTextValue('scriptText2',scriptText2);
      ggbApplet.setTextValue('scriptText3',scriptText3);
      ggbApplet.evalCommand('Execute[{scriptText1,scriptText2,scriptText3}]');
    }
  }
}

//(edit終了時に実行を想定)copycarのfixを解除、選択許可(setfixedをfalse,true)、copycarにOUSを設定、ゲームのルールに合った挙動にする
function getCopycarReady(){
  var red = isRedExists();
  if(!ggbApplet.getValue('edit') && red==-1){
    ggbApplet.evalCommand('SetValue[alert,true]');
    ggbApplet.evalCommand('SetValue[edit,true]');
    ggbApplet.evalCommand('RunUpdateScript[edit]');
    return;
  }

  var copycars = getExistingObjIndex('copycar');
  //赤い車の名前を取得、ゴール時の演出
  if(!ggbApplet.getValue('edit')){
    ggbApplet.setTextValue('redCarName', 'copycar'+copycars[red]);
    ggbApplet.evalCommand('isEnd = If[x(CENTER'+copycars[red]+') > x(goalMidPoint),true,false]');
    ggbApplet.evalCommand('SetConditionToShowObject[prizeText, ¬edit&&isEnd]');
  }
  else{
    ggbApplet.evalCommand('SetConditionToShowObject[prizeText, ¬edit]');
  }
  //fixを解除、OUSを設定
  if(!ggbApplet.getValue('edit')){
    for(var k=0; k < copycars.length; k++){
      ggbApplet.setFixed('copycar'+copycars[k], false, true);

      var script1 = 'SetValue[CENTER'+copycars[k]+',Midpoint[Corner[copycar'+copycars[k]+',1],Corner[copycar'+copycars[k]+',3]]]';
      var script2 = 'SetValue[copycar'+copycars[k]+',Translate[copycar'+copycars[k]+',Vector[Midpoint[Corner[copycar'+copycars[k]+',1],Corner[copycar'+copycars[k]+',3]],CENTER'+copycars[k]+']]]';
      var script3 = 'SetValue[START'+copycars[k]+',Dilate[Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]], (-0.4 + Distance[Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]], Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]]]) / Distance[Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]], Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]]], Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]]]]';
      var script4 = 'SetValue[GOAL'+copycars[k]+',Dilate[Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]], (-0.4 + Distance[Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]], Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]]]) / Distance[Midpoint[Corner[copycar'+copycars[k]+', 1], Corner[copycar'+copycars[k]+', 4]], Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]]], Midpoint[Corner[copycar'+copycars[k]+', 2], Corner[copycar'+copycars[k]+', 3]]]]';
      var script5 = 'updateRange('+copycars[k]+')';
      var scriptToSet = 'ggbApplet.evalCommand(\''+script1+'\'); \n ggbApplet.evalCommand(\''+script2+'\'); \n ggbApplet.evalCommand(\''+script3+'\'); \n ggbApplet.evalCommand(\''+script4+'\'); \n '+script5+';';
     setJavaScript('copycar'+copycars[k], 'update', scriptToSet);
    }
  }
}