GASでJuliamoフォントのエスペラント語の単語帳を作る

三番煎じです。
元ネタ→https://qiita.com/Suibari_cha/items/87503c55d984ff0f43e6

詳しいこととかは元ネタの方を見てください。
せっかちな方はこちら→https://script.google.com/macros/s/AKfycby3C-LStoIC5Wk5TFAviFGAjq_sKqg5WsUYr96Ae0_rusduI04/exec

単語帳はここからお借りしました→http://www2.tokai.or.jp/esperanto/kihongoi.html

さっそくコード

```javascript:コード.gs
// GASが呼び出されたときに実行。HTMLを表示する
function doGet(e) {
  var apliko = HtmlService.createHtmlOutputFromFile("indekso")
  return apliko;
}

// スプレッドシート処理関数
function nova_kvizo_servilo(datumoj,nunatuko)
{
  const maksimuma_kvanto = 10; // 最大出題回数
  // スプレッドシート処理
  var tuko=
    SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/11mIHj6SsdhyAhD5i4yKXpRUr33xxhPyvWmP_d12j8rs/edit?usp=sharing')
      .getSheetByName(nunatuko);
  if(nunatuko==""){
   tuko = 
      SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/11mIHj6SsdhyAhD5i4yKXpRUr33xxhPyvWmP_d12j8rs/edit?usp=sharing')
      .getSheets()[0];
    nunatuko=tuko.getName()
  }
  var maksimuma_linio = tuko.getLastRow() - 1;
  // 全行からランダムに1行選択
  var r = Math.floor(Math.random() * maksimuma_linio) + 2; 
  if (datumoj.length!=0){
    while(true){
    r = Math.floor(Math.random() * maksimuma_linio) + 2; 
    if(datumoj.indexOf(""+r)==-1)break;  //indexOfは型まで含めた厳密な型変換だったんですね…
    }
  }
  // 問題文、回答文、出題回数の取得
  var teksto_kvizo   = tuko.getRange("B" + r).getValue()
  var teksto_respondo = tuko.getRange("C" + r).getValue();
  
  //シート名の取得
  var tukoj = [];
  if (SpreadsheetApp.getActiveSpreadsheet().getSheets().length >= 1) {  
    SpreadsheetApp.getActiveSpreadsheet().getSheets().forEach(function(tuko) {
        tukoj.push(tuko.getName());
    });
  }


  return [teksto_kvizo, teksto_respondo,r,tukoj];

}
```

```html:indekso.html
<html>
  <head>
    <title>Kvizo Reteja Aplika</title>
    <script>
 
    // ボタンがクリックされたとき呼び出されるハンドラ
    function suralkakubutonon(){

      // html読み取り
      var retejo = document.getElementById("retejo");
      var butono = document.getElementById("butono");

      if(retejo.style.visibility == "hidden"){
        // 答えが表示されていないので、答えを表示しボタンを「sekvonta problemo」に
        butono.innerHTML = "sekvonta problemo";
        retejo.style.visibility = "visible";
      } else {
        var datumoj=importo()
        if (typeof datumoj[document.getElementById("tuko").value] == "undefined")datumoj[document.getElementById("tuko").value]=[]
        if(document.getElementById("kontrolo").checked==true){
        //cookieへの書き込み
        datumoj[document.getElementById("tuko").value].push(document.getElementById("nun").innerHTML)
        eksporto(datumoj);
        }
        if(datumoj[document.getElementById("tuko").value].length==0){
        nova_kvizo([],document.getElementById("tuko").value)
        }else{
        nova_kvizo(datumoj[document.getElementById("tuko").value],document.getElementById("tuko").value);
        }
        document.getElementById("kontrolo").checked==false
        // 答えが表示されているので、問題・答えを取得して答えを非表示にしボタンを「vidi respondon」に        
        butono.innerHTML = "vidi respondon";
        retejo.style.visibility = "hidden";

      }
    }

    // サーバ側スクリプトnova_kvizo_servilo()が実行成功したとき呼び出されるハンドラ
    function onSuccess (res){
      // html読み取り
      var kvizo = document.getElementById("kvizo");
      var retejo = document.getElementById("retejo");
      var nun = document.getElementById("nun");
      var tuko = document.getElementById("tuko");
      // 問題のセット
      kvizo.innerHTML = res[0];
      // 回答のセット
      retejo.innerHTML = res[1];
      retejo.style.visibility = "hidden";
      //今の問題のID
      nun.innerHTML=res[2]
      //選択できるシート名を変える
      tukoj=res[3]
      tuko.textContent = null;
      for(var i=0;i<tukoj.length;i++){
        var elemento = document.createElement('option');
        elemento.appendChild(document.createTextNode(tukoj[i]));
        elemento.value = tukoj[i];
        tuko.appendChild(elemento);
      }
    }
    
    function importo() {
    // シート名が変わったりカンマがはいったりした時のためにめんどくさい処理をしています
      if(document.cookie!=""){
      var historioj=document.cookie.substring(document.cookie.indexOf("juliamo=")+8).split("-")
      var kapoj=[]
      var longoj=[]
      for(var i=0; 2*i<historioj.length-1;i++){
      kapoj.push(parseInt(historioj[2*i]))    //シート名の文字数
      longoj.push(parseInt(historioj[2*i+1]))  //シートの要素数
      }
      var tukoj=[]; //シート名
      var historio=decodeURIComponent(historioj[historioj.length-1])
      var komenco=0  //文字列のどこをみるか
      var datumoj=[] //データ
      for(var i=0;i<kapoj.length;i++){
        tukoj.push(historio.substr(komenco,kapoj[i]))
        komenco+=kapoj[i]
        datumoj[tukoj[i]]=[]
        for(var j=0;j<longoj[i];j++){
          datumoj[tukoj[i]].push(historio.substr(komenco+1).split(",")[j])
        }
        komenco+=2+datumoj[tukoj[i]].join(",").length
      }
      }else{
      var datumoj=[]
      }
      return datumoj
    }
    
    function eksporto(datumoj) {
      var tukoj=Object.keys(datumoj)
      var kapoj=[];
      var longoj=[];
      var historio="";
      tukoj.forEach(function(tuko) {
        kapoj.push(tuko.length)
        longoj.push(datumoj[tuko].length)
        historio+=tuko+","+datumoj[tuko].join(",")
      })
      historio=encodeURIComponent(historio)
      
      for(var i=kapoj.length-1;i>-1;i--){
        historio=longoj[i]+"-"+historio
        historio=kapoj[i]+"-"+historio
      }
      document.cookie="juliamo="+historio+";max-age=60*60*24*30"
    }
    // サーバサイド関数を稼働させて、問題・答えを取得する関数
    function nova_kvizo(datumoj,tuko) {
      return google.script.run.withSuccessHandler(onSuccess).nova_kvizo_servilo(datumoj,tuko);
    }

    </script>
    <style>
    @font-face {
      font-family: 'juliamo-font';
      src: url('https://dl.dropboxusercontent.com/s/5me44aeb19mxm6e/juliamo.woff') format('woff');
      }
    body{
      font:100% "juliamo-font";
    }
  </style>
  </head>
  <body>
    <table style="width: 100%;height:100%" cellspacing="100" cellpadding="0">
      <tbody>
        <tr>
          <td>
           <select id="tuko">
           </select>
          <span id="nun"></span>
            <input type="checkbox" id="kontrolo">memoris
          </td>
        </tr>
        <tr>
          <td style="vertical-align: top;" align="left">
            <div id="kvizo" style="font-size: 300%;"><br></div>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: top;" align="left">
            <button type="button" id="butono" style="font:100% juliamo-font;width: 100%; height: 200%; color: white; background: rgb(80, 184, 216) none repeat scroll 0% 0%; font-size: 300%;" onclick="suralkakubutonon()">vidi respondon</button>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: top;" align="left">
            <div id="retejo" style="font-size: 300%;"></div>
          </td>
        </tr>
      </tbody>
    </table>
    <script>
    // 最初にHTMLが読み込まれたときに問題・答えを設定する
    var datumo=importo()
    if(datumo.length==0){
    nova_kvizo([],"")
    }else{
    //最初はcookieにある最初のインデックスのシートを適用
    nova_kvizo(datumo[Object.keys(datumo)[0]],Object.keys(datumo)[0]);
    }
</script>
  </body>
</html>
```

いじったこととして

* ユリアーモフォントの追加
* 個人用から共用
* シートの選択の追加
* cookieによるデータ保存
* 表示のエスペラント化。
* ついでに見えない部分（変数）もエスペラント化

なんですがググればどれもでてきそうなものばかりでいまひとつなんですよね。
cookieの導入を書きたいですがずいぶんとふくれあがってcookieの説明だけで1ページできそう。素直にライブラリもってこればよかったかな。
それと使ってみた感想なのですがボタンをおして帰ってくるまでのラグがひどいなと思います。GASをやめて専用でサーバーたてればよくなるのでしょうか…