TinyGrail Helper Remake

为小圣杯增加一些小功能

当前为 2020-10-13 提交的版本,查看 最新版本

// ==UserScript==
// @name        TinyGrail Helper Remake
// @description 为小圣杯增加一些小功能
// @namespace   inqb.ga
// @version     2.4.10
// @author      Liaune, Cedar, no1xsyzy (InQβ)
// @include     /^https?://(bgm\.tv|bangumi\.tv|chii\.in)/(user|character|rakuen\/topiclist|rakuen\/home|rakuen\/topic\/crt).*
// @grant       GM_style
// ==/UserScript==

(function ($) {
  'use strict';

  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

  var $__default = /*#__PURE__*/_interopDefaultLegacy($);

  function styleInject(css, ref) {
    if ( ref === void 0 ) ref = {};
    var insertAt = ref.insertAt;

    if (!css || typeof document === 'undefined') { return; }

    var head = document.head || document.getElementsByTagName('head')[0];
    var style = document.createElement('style');
    style.type = 'text/css';

    if (insertAt === 'top') {
      if (head.firstChild) {
        head.insertBefore(style, head.firstChild);
      } else {
        head.appendChild(style);
      }
    } else {
      head.appendChild(style);
    }

    if (style.styleSheet) {
      style.styleSheet.cssText = css;
    } else {
      style.appendChild(document.createTextNode(css));
    }
  }

  var css_248z = "ul.timelineTabs li a {\n  margin: 2px 0 0 0;\n  padding: 5px 10px 5px 10px;\n}\n\nimg.cover {\n  background-color: transparent;\n}\n\n.assets .my_temple.item .card {\n  box-shadow: 3px 3px 5px #FFEB3B;\n  border: 1px solid #FFC107;\n}\n\nhtml[data-theme='dark'] .assets .my_temple.item .card {\n  box-shadow: 0px 0px 15px #FFEB3B;\n  border: 1px solid #FFC107;\n}\n\n.assets .my_temple.item .name a {\n  font-weight: bold;\n  color: #0084b4;\n}\n\n#grail .temple_list .item {\n  margin: 5px 5px 5px 0;\n  width: 107px;\n}\n\n.assets_box .item {\n  margin: 5px 5px 5px 0;\n  width: 90px;\n}\n\n#lastTemples .assets .item {\n  margin: 5px 5px 5px 0;\n  width: 107px;\n}\n\n.item .card {\n  width: 105px;\n  height: 140px;\n}\n\n.assets_box .item .card {\n  width: 90px;\n  height: 120px;\n}\n\n#grailBox .my_auction,\n#TB_window .my_auction {\n  color: #ffa7cc;\n  margin-right: 5px;\n}\n\n#grailBox .user_auction,\n#TB_window .user_auction {\n  color: #a7e3ff;\n  margin-right: 5px;\n}\n\nhtml[data-theme='dark'] #grailBox .title {\n  background-color: transparent;\n}\n\n#grailBox .trade_box button {\n  min-width: 50px;\n  padding: 0 9px;\n}\n\n#TB_window .text_button {\n  margin: 0 8px 0 0;\n  padding: 0;\n  width: fit-content;\n  height: fit-content;\n  min-width: fit-content;\n  color: #0084B4;\n}\n";
  styleInject(css_248z);

  function launchObserver( {
    parentNode,
    selector,
    failCallback = null,
    successCallback = null,
    stopWhenSuccess = true,
    config = {
      'childList': true,
      'subtree': true
    },
  } ) {
    // if parent node does not exist, return
    if ( !parentNode )
      return;
    const observeFunc = mutationList => {
      if ( !document.querySelector( selector ) ) {
        if ( failCallback )
          failCallback();
        return;
      }
      if ( stopWhenSuccess )
        observer.disconnect();
      if ( successCallback )
        successCallback();
    };
    let observer = new MutationObserver( observeFunc );
    observer.observe( parentNode, config );
  }

  const API = 'https://tinygrail.com/api/';

  function getData( url ) {
    if ( !url.startsWith( 'http' ) ) url = API + url;
    return new Promise( ( resovle, reject ) => {
      $__default['default'].ajax( {
        url: url,
        type: 'GET',
        xhrFields: {
          withCredentials: true
        },
        success: res => {
          resovle( res );
        },
        error: err => {
          reject( err );
        }
      } );
    } );
  }

  function postData( url, data ) {
    let d = JSON.stringify( data );
    if ( !url.startsWith( 'http' ) ) url = api + url;
    return new Promise( ( resovle, reject ) => {
      $__default['default'].ajax( {
        url: url,
        type: 'POST',
        contentType: 'application/json',
        data: d,
        xhrFields: {
          withCredentials: true
        },
        success: res => {
          resovle( res );
        },
        error: err => {
          reject( err );
        }
      } );
    } );
  }

  function defineStorage( name, default_value ) {
    if ( !( name in localStorage ) ) {
      localStorage.setItem( name, JSON.stringify( default_value ) );
    }

    function getter() {
      return JSON.parse( localStorage.getItem( name ) );
    }

    function setter( v ) {
      localStorage.setItem( name, JSON.stringify( v ) );
    }
    return [ getter, setter ];
  }

  let [ getSettings$1, setSettings ] = defineStorage( 'TinyGrail_settings', {
    "pre_temple": "on",
    "hide_grail": "off",
    "auction_num": "one",
    "merge_order": "off",
    "get_bonus": "on",
    "gallery": "off",
    "auto_fill_temple": "off"
  } );

  let [ getItemsSetting, setItemsSetting ] = defineStorage( 'TinyGrail_ItemsSetting', {} );

  let ItemsSetting = getItemsSetting();

  //自动补塔
  function autoFillTemple() {
    if ( getSettings$1().auto_fill_temple != 'on' )
      return;
    async function autoFillCosts( autoFillCostList ) {
      for ( let i = 0; i < autoFillCostList.length; i++ ) {
        let id = autoFillCostList[ i ].id;
        let supplyId = autoFillCostList[ i ].supplyId;
        let cost = autoFillCostList[ i ].cost;
        await postData( `magic/stardust/${supplyId}/${id}/${cost}/true`, null ).then( ( d ) => {
          if ( d.State == 0 )
            console.log( `自动补塔 #${id} ${d.Value}` );
          else
            console.log( `自动补塔 #${id} ${d.Message}` );
        } );
      }
    }

    function checkLostTemple( currentPage ) {
      let autoFillCostList = [];
      getData( `chara/user/temple/0/${currentPage}/500` ).then( ( d ) => {
        if ( d.State == 0 ) {
          for ( let i = 0; i < d.Value.Items.length; i++ ) {
            let info = {};
            let lv = d.Value.Items[ i ].CharacterLevel;
            info.id = d.Value.Items[ i ].CharacterId;
            info.supplyId = ItemsSetting.stardust ? ItemsSetting.stardust[ lv ] : null;
            info.cost = d.Value.Items[ i ].Sacrifices - d.Value.Items[ i ].Assets;
            if ( info.cost >= 100 && info.cost <= 250 && info.id != info.supplyId && info.supplyId ) {
              autoFillCostList.push( info );
            }
          }
          autoFillCosts( autoFillCostList );
          if ( currentPage < d.Value.TotalPages ) {
            checkLostTemple( currentPage + 1 );
          }
        }
      } );
    }
    checkLostTemple( 1 );
  }

  let [ getAutoTempleList$1, setAutoTempleList ] = defineStorage( 'TinyGrail_autoTempleList', [] );

  function formatDate( date ) {
    date = new Date( date );
    return date.format( 'yyyy-MM-dd hh:mm:ss' );
  }
  function formatTime( timeStr ) {
    let now = new Date();
    let time = new Date( timeStr ) - ( new Date().getTimezoneOffset() + 8 * 60 ) * 60 * 1000;

    let times = ( time - now ) / 1000;
    let day = 0;
    let hour = 0;
    let minute = 0;
    let second = 0;
    if ( times > 0 ) {
      day = Math.floor( times / ( 60 * 60 * 24 ) );
      hour = Math.floor( times / ( 60 * 60 ) ) - Math.floor( times / ( 60 * 60 * 24 ) ) * 24;
      minute = Math.floor( times / 60 ) - Math.floor( times / ( 60 * 60 ) ) * 60;

      if ( day > 0 )
        return `剩余${day}天${hour}小时`;
      else if ( hour > 0 )
        return `剩余${hour}小时${minute}分钟`;
      else
        return `即将结束 剩余${minute}分钟`;
      //return '即将结束';
    } else {
      times = Math.abs( times );
      day = Math.floor( times / ( 60 * 60 * 24 ) );
      hour = Math.floor( times / ( 60 * 60 ) );
      minute = Math.floor( times / 60 );
      second = Math.floor( times );

      if ( minute < 1 ) {
        return `${second}s ago`;
      } else if ( minute < 60 ) {
        return `${minute}m ago`;
      } else if ( hour < 24 ) {
        return `${hour}h ago`;
      }

      if ( day > 1000 )
        return 'never';

      return `[${new Date(timeStr).format('yyyy-MM-dd')}] ${day}d ago`;
    }
  }
  function formatNumber( number, decimals, dec_point, thousands_sep ) {
    number = ( number + '' ).replace( /[^0-9+-Ee.]/g, '' );
    let n = !isFinite( +number ) ? 0 : +number,
      prec = !isFinite( +decimals ) ? 2 : Math.abs( decimals ),
      sep = ( typeof thousands_sep === 'undefined' ) ? ',' : thousands_sep,
      dec = ( typeof dec_point === 'undefined' ) ? '.' : dec_point,
      s = '';
    // toFixedFix = function (n, prec) {
    //   let k = Math.pow(10, prec);
    //   return '' + Math.ceil(n * k) / k;
    // };
    //s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
    s = ( prec ? n.toFixed( prec ) : '' + Math.round( n ) ).split( '.' );
    let re = /(-?\d+)(\d{3})/;
    while ( re.test( s[ 0 ] ) ) {
      s[ 0 ] = s[ 0 ].replace( re, "$1" + sep + "$2" );
    }

    if ( ( s[ 1 ] || '' ).length < prec ) {
      s[ 1 ] = s[ 1 ] || '';
      s[ 1 ] += new Array( prec - s[ 1 ].length + 1 ).join( '0' );
    }
    return s.join( dec );
  }
  function formatAskPrice( price ) {
    if ( Number.isInteger( parseFloat( price ) ) )
      return price;

    else
      return ( price - Math.floor( price ) ) > 0.5 ? Math.ceil( price ) : Math.floor( price ) + 0.5;
  }

  function remove_empty( array ) {
    let arr = [];
    for ( let i = 0; i < array.length; i++ ) {
      if ( array[ i ] )
        arr.push( array[ i ] );
    }
    return arr;
  }

  function removeBuildTemple( charaId ) {
    let autoTempleList = getAutoTempleList();
    for ( let i = 0; i < autoTempleList.length; i++ ) {
      if ( autoTempleList[ i ].charaId == charaId ) {
        autoTempleList.splice( i, 1 );
        break;
      }
    }
    $__default['default']( '#autobuildButton' ).text( '[自动建塔]' );
    setAutoTempleList( autoTempleList );
  }

  async function autoBuildTemple( charas ) {
    function buildTemple( chara, amount ) {
      postData( `chara/sacrifice/${chara.charaId}/${amount}/false`, null ).then( ( d ) => {
        if ( d.State == 0 ) {
          console.log( `#${chara.charaId} ${chara.name} 献祭${amount} 获得金额 ₵${d.Value.Balance.toFixed(2)}` );
          $__default['default']( '#autobuildButton' ).text( '[自动建塔]' );
          removeBuildTemple( chara.charaId );
        } else {
          console.log( `${d.Message}` );
        }
      } );
    }

    function postBid( chara, price, amount, Amount, Sacrifices ) {
      postData( `chara/bid/${chara.charaId}/${price}/${amount}`, null ).then( ( d ) => {
        if ( d.Message )
          console.log( `#${chara.charaId} ${chara.name} ${d.Message}` );
        else {
          console.log( `买入成交 #${chara.charaId} ${chara.name} ${price}*${amount}` );
          if ( ( Amount + Sacrifices + amount ) >= chara.target ) { //持股达到数量,建塔
            buildTemple( chara, chara.target - Sacrifices );
          }
        }
      } );
    }

    function getAskin( Asks, low_price ) {
      let [ price, amount ] = [ 0, 0 ];
      for ( let i = 0; i < Asks.length; i++ ) {
        if ( Asks[ i ].Price > 0 && Asks[ i ].Price <= low_price ) {
          amount += Asks[ i ].Amount;
          price = Asks[ i ].Price;
        }
      }
      return [ price, amount ];
    }

    function remove_myAsks( Asks, myAsks ) {
      for ( let i = 0; i < Asks.length; i++ ) {
        for ( let j = 0; j < myAsks.length; j++ ) {
          if ( formatAskPrice( Asks[ i ].Price ) == formatAskPrice( myAsks[ j ].Price ) )
            Asks[ i ].Amount -= myAsks[ j ].Amount;
        }
        if ( Asks[ i ].Amount == 0 )
          delete Asks[ i ];
      }
      Asks = remove_empty( Asks );
      return Asks;
    }
    for ( let i = 0; i < charas.length; i++ ) {
      let chara = charas[ i ];
      console.log( `自动建塔 check #${chara.charaId} ${chara.name}` );
      await getData( `chara/user/${chara.charaId}` ).then( ( d ) => {
        let myAsks = d.Value.Asks;
        let Amount = d.Value.Amount;
        let Sacrifices = d.Value.Sacrifices;
        if ( Sacrifices >= chara.target ) {
          removeBuildTemple( chara.charaId );
        } else if ( ( Amount + Sacrifices ) >= chara.target ) { //持股达到数量,建塔
          buildTemple( chara, chara.target - Sacrifices );
        } else
          getData( `chara/depth/${chara.charaId}` ).then( ( d ) => {
            let Asks = d.Value.Asks;
            Asks = remove_myAsks( Asks, myAsks );
            //console.log(Asks);
            let AskPrice = Asks[ 0 ] ? Asks[ 0 ].Price : 0;
            if ( AskPrice && AskPrice <= chara.bidPrice ) { //最低卖单低于买入上限,买入
              let [ price, amount ] = getAskin( Asks, chara.bidPrice );
              postBid( chara, price, Math.min( amount, chara.target - Amount - Sacrifices ), Amount, Sacrifices );
            }
          } );
      } );
    }
  }

  function autoTemple() {
    let autoTempleList = getAutoTempleList$1();
    if ( autoTempleList.length )
      autoBuildTemple( autoTempleList );
  }

  let [ getFillICOList, setFillICOList ] = defineStorage( 'TinyGrail_fillicoList', [] );

  function caculateICO( ico ) {
    let level = 0;
    let price = 0;
    let amount = 0;
    let next = 100000;
    let nextUser = 15;

    //人数等级
    let heads = ico.Users;
    let headLevel = Math.floor( ( heads - 10 ) / 5 );
    if ( headLevel < 0 )
      headLevel = 0;

    //资金等级
    while ( ico.Total >= next && level < headLevel ) {
      level += 1;
      next += Math.pow( level + 1, 2 ) * 100000;
    }
    if ( level ) {
      amount = 10000 + ( level - 1 ) * 7500;
      price = ico.Total / amount;
    }
    nextUser = ( level + 1 ) * 5 + 10;

    return {
      Level: level,
      Next: next,
      Price: price,
      Amount: amount,
      Users: nextUser - ico.Users
    };
  }

  function ICO_standard( lv ) {
    let users = lv * 5 + 10;
    let total = 100000;
    let level = 1;
    while ( lv > level ) {
      level++;
      total += Math.pow( level, 2 ) * 100000;
    }
    return {
      Users: users,
      Total: total
    };
  }

  function closeDialog() {
    $__default['default']( '#TB_overlay' ).remove();
    $__default['default']( '#TB_window' ).remove();
  }

  async function fullfillICO( icoList ) {
    var dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<div class="info_box">
<div class="title">自动补款检测中</div>
<div class="result" style="max-height:500px;overflow:auto;"></div>
</div>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>
</div>`;
    if ( !$__default['default']( '#TB_window' ).length )
      $__default['default']( 'body' ).append( dialog );
    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );
    $__default['default']( '#TB_overlay' ).on( 'click', closeDialog );
    for ( let i = 0; i < icoList.length; i++ ) {
      let Id = icoList[ i ].Id;
      let charaId = icoList[ i ].charaId;
      let targetlv = icoList[ i ].target;
      let target = ICO_standard( targetlv );
      await getData( `chara/${charaId}` ).then( ( d ) => {
        if ( d.State == 0 ) {
          let predicted = caculateICO( d.Value );
          if ( predicted.Level >= targetlv ) {
            console.log( charaId + '总额:' + d.Value.Total + ',已达标,无需补款' );
            $__default['default']( '.info_box .result' ).prepend( `<div class="row">#${charaId} 目标: lv${targetlv} 总额: ${d.Value.Total} ,已达标,无需补款</div>` );
          } else if ( predicted.Users <= 0 ) {
            let offer = predicted.Next - d.Value.Total;
            if ( d.Value.Users >= target.Users ) {
              offer = target.Total - d.Value.Total;
            }
            offer = Math.max( offer, 5000 );
            postData( `chara/join/${Id}/${offer}`, null ).then( ( d ) => {
              if ( d.State === 0 ) {
                $__default['default']( '.info_box .result' ).prepend( `<div class="row">#${charaId} 目标: lv${targetlv} 补款: ${offer}</div>` );
                console.log( charaId + '补款:' + offer );
              } else {
                $__default['default']( '.info_box .result' ).prepend( `<div class="row">#${charaId} ${d.Message}</div>` );
                console.log( d.Message );
              }
            } );
          } else {
            $__default['default']( '.info_box .result' ).prepend( `<div class="row">#${charaId} 目标: lv${targetlv} 人数: ${d.Value.Users}, 人数不足,未补款</div>` );
            console.log( charaId + '人数:' + d.Value.Users + ',人数不足,未补款' );
          }
        }
      } );
    }
  }

  function fillICO() {
    let fillicoList = getFillICOList();
    let icoList = [];
    for ( let i = 0; i < fillicoList.length; i++ ) {
      let endTime = new Date( new Date( fillicoList[ i ].end ) - ( new Date().getTimezoneOffset() + 8 * 60 ) * 60 * 1000 );
      let leftTime = ( new Date( endTime ).getTime() - new Date().getTime() ) / 1000; //剩余时间:秒
      if ( leftTime < 60 ) {
        console.log( `ico check#${fillicoList[i].charaId} -「${fillicoList[i].name}」 目标等级:lv${fillicoList[i].target} ${leftTime}s left` );
        icoList.push( fillicoList[ i ] );
        delete fillicoList[ i ];
      }
    }
    fillicoList = remove_empty( fillicoList );
    setFillICOList( fillicoList );
    if ( icoList.length )
      fullfillICO( icoList );
  }

  function getWeeklyShareBonus( callback ) {
    if ( !confirm( '已经周六了,赶紧领取股息吧?' ) )
      return;

    getData( `event/share/bonus` ).then( d => {
      if ( d.State == 0 )
        alert( d.Value );

      else
        alert( d.Message );
      callback();
    } );
  }

  function getShareBonus() {
    let asiaTime = new Date().toLocaleString( "en-US", {
      timeZone: "Asia/Shanghai"
    } );
    asiaTime = new Date( asiaTime );
    let Day = asiaTime.getDay();
    if ( Day == 6 ) {
      getData( 'event/share/bonus/check' ).then( ( d ) => {
        if ( d.State === 0 ) {
          getWeeklyShareBonus();
        }
      } );
    }
  }

  function hideBonusButton() {
    if ( !$__default['default']( '#bonusButton' ).length )
      return;
    getData( 'event/share/bonus/test' ).then( ( d ) => {
      let x = d.Value.Share / 10000;
      let allowance = Math.log10( x + 1 ) * 30 - x;
      if ( d.State == 0 && allowance < 0 )
        $__default['default']( '#bonusButton' ).remove();
      //else $('#shareBonusButton').hide();
    } );
  }

  function menuItemClicked( callback ) {
    $__default['default']( '.timelineTabs a' ).removeClass( 'focus' );
    $__default['default']( '.timelineTabs a' ).removeClass( 'top_focus' );
    $__default['default']( '#helperMenu' ).addClass( 'focus' );
    if ( callback )
      callback( 1 );
  }

  function openSettings() {
    closeDialog();
    let settings = getSettings$1();
    let dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<table align="center" width="98%" cellspacing="0" cellpadding="5" class="settings">
<tbody><tr><td valign="top" width="50%">主页显示/隐藏小圣杯</td><td valign="top">
<select id="set1"><option value="off" selected="selected">显示</option><option value="on">隐藏</option></select></td></tr>
<tr><td valign="top" width="50%">将自己圣殿排到第一个显示</td><td valign="top">
<select id="set2"><option value="on" selected="selected">是</option><option value="off">否</option></td></tr>
<tr><td valign="top" width="50%">默认拍卖数量</td><td valign="top">
<select id="set3"><option value="one" selected="selected">1</option><option value="all">全部</option></td></tr>
<tr><td valign="top" width="50%" title="合并同一时间同一价格的历史订单记录">合并历史订单</td><td valign="top">
<select id="set4"><option value="on" selected="selected">是</option><option value="off">否</option></td></tr>
<tr><td valign="top" width="50%">周六自动提醒领取股息</td><td valign="top">
<select id="set5"><option value="on" selected="selected">是</option><option value="off">否</option></td></tr>
<tr><td valign="top" width="50%">圣殿画廊</td><td valign="top">
<select id="set6"><option value="off" selected="selected">关</option><option value="on">开</option></td></tr>
<tr><td valign="top" width="50%">自动补塔</td><td valign="top">
<select id="set7"><option value="off" selected="selected">关</option><option value="on">开</option></td></tr>
<tr><td valign="top" width="12%"><input class="inputBtn" value="保存" id="submit_setting" type="submit"></td><td valign="top"></td></tr>
</tbody></table>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>
</div>`;
    $__default['default']( 'body' ).append( dialog );
    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );
    $__default['default']( '#TB_overlay' ).on( 'click', closeDialog );
    $__default['default']( '#set1' ).val( settings.hide_grail );
    $__default['default']( '#set2' ).val( settings.pre_temple );
    $__default['default']( '#set3' ).val( settings.auction_num );
    $__default['default']( '#set4' ).val( settings.merge_order );
    $__default['default']( '#set5' ).val( settings.get_bonus );
    $__default['default']( '#set6' ).val( settings.gallery );
    $__default['default']( '#set7' ).val( settings.auto_fill_temple );
    $__default['default']( '#submit_setting' ).on( 'click', () => {
      settings.hide_grail = $__default['default']( '#set1' ).val();
      settings.pre_temple = $__default['default']( '#set2' ).val();
      settings.auction_num = $__default['default']( '#set3' ).val();
      settings.merge_order = $__default['default']( '#set4' ).val();
      settings.get_bonus = $__default['default']( '#set5' ).val();
      settings.gallery = $__default['default']( '#set6' ).val();
      settings.auto_fill_temple = $__default['default']( '#set7' ).val();
      setSettings( settings );
      $__default['default']( '#submit_setting' ).val( '已保存' );
      setTimeout( () => {
        closeDialog();
      }, 500 );
    } );
  }

  function normalizeAvatar( avatar ) {
    if ( !avatar )
      return '//lain.bgm.tv/pic/user/l/icon.jpg';

    if ( avatar.startsWith( 'https://tinygrail.oss-cn-hangzhou.aliyuncs.com/' ) )
      return avatar + "!w120";

    let a = avatar.replace( "http://", "//" );
    return a;
  }

  function cancelBids() {
    if ( !confirm( "取消全部买单?" ) )
      return;
    $__default['default']( '#eden_tpc_list ul' ).html( '' );
    getData( `chara/user/assets` ).then( ( d ) => {
      let Balance = d.Value.Balance;
      getData( `chara/bids/0/1/1000` ).then( ( d ) => {
        cancel_All_Bids( d.Value.Items, Balance );
      } );
    } );
  }

  async function cancel_All_Bids( charas, Balance ) {
    for ( let i = 0; i < charas.length; i++ ) {
      let id = charas[ i ].Id;
      let name = charas[ i ].Name;
      let avatar = `<a href="/rakuen/topic/crt/${id}?trade=true" class="avatar l" target="right"><span class="avatarNeue avatarReSize32 ll" style="background-image:url('${normalizeAvatar(charas[i].Icon)}')"></span></a>`;
      await getData( `chara/user/${id}` ).then( ( d ) => {
        let line = 'line_even';
        if ( i % 2 == 0 )
          line = 'line_odd';
        let tid = d.Value.Bids[ 0 ].Id;
        let price = d.Value.Bids[ 0 ].Price;
        let amount = d.Value.Bids[ 0 ].Amount;
        Balance += price * amount;
        postData( `chara/bid/cancel/${tid}`, null ).then( ( d ) => {
          let message = `<li class="${line} item_list item_log" data-id="${id}">${avatar}<span class="tag raise">+${formatNumber(price * amount, 2)}</span>
₵${formatNumber(Balance, 2)}<span class="row"><small class="time">取消买单(${tid}) #${id} 「${name}」 ${price}*${amount}</small></span></li>`;
          $__default['default']( '#eden_tpc_list ul' ).prepend( message );
        } );
      } );
    }
  }

  let [ getCharaInitPrice, setCharaInitPrice ] = defineStorage( 'TinyGrail_chara_initPrice', {} );

  let chara_initPrice;

  function sellOut() {
    chara_initPrice = getCharaInitPrice();
    $__default['default']( `#eden_tpc_list .item_list` ).removeAttr( 'onclick' );
    $__default['default']( '#eden_tpc_list .item_list' ).each( ( i, e ) => {
      let id = $__default['default']( e ).data( 'id' );
      let sell_btn = `<span><small data-id="${id}" class="sell_btn">[卖出]</small></span>`;
      if ( !$__default['default']( e ).find( '.sell_btn' ).length ) {
        $__default['default']( `#eden_tpc_list li[data-id=${id}] .row` ).append( sell_btn );
      }
    } );
    $__default['default']( '.sell_btn' ).on( 'click', ( e ) => {
      let id = $__default['default']( e.target ).data( 'id' );
      if ( id ) {
        let price_tag = $__default['default']( `#eden_tpc_list li[data-id=${id}]` ).find( 'div.tag' )[ 0 ].innerText.match( /₵([0-9]*(\.[0-9]{1,2})?)/ );
        let price_now = price_tag ? price_tag[ 1 ] : 0; //获取抽奖时买价
        getData( `chara/${id}` ).then( ( d ) => {
          let initPrice = chara_initPrice[ id ] ? chara_initPrice[ id ].init_price : d.Value.Price;
          let price = Math.max( parseFloat( price_now ), parseFloat( initPrice ).toFixed( 2 ), d.Value.Current.toFixed( 2 ) );
          getData( `chara/user/${id}` ).then( ( d ) => {
            let amount = d.Value.Amount;
            if ( amount ) {
              postData( `chara/ask/${id}/${price}/${amount}`, null ).then( ( d ) => {
                if ( d.Message )
                  console.log( `#${id}: ${d.Message}` );
                else
                  console.log( `卖出委托#${id} ${price}*${amount}` );
              } );
            }
          } );
        } );
      }
      $__default['default']( `#eden_tpc_list li[data-id=${id}]` ).remove();
    } );
  }

  let [ getFollowList, setFollowList ] = defineStorage( 'TinyGrail_followList', {
    "user": '',
    "charas": [],
    "auctions": []
  } );

  function listItemClicked() {
    let link = $__default['default']( this ).find( 'a.avatar' ).attr( 'href' );
    if ( link ) {
      if ( parent.window.innerWidth < 1200 ) {
        $__default['default']( parent.document.body ).find( "#split #listFrameWrapper" ).animate( {
          left: '-450px'
        } );
      }
      window.open( link, 'right' );
    }
  }

  function renderBalanceLog( item, even ) {
    var line = 'line_odd';
    if ( even )
      line = 'line_even';

    var change = '';
    if ( item.Change > 0 )
      change = `<span class="tag raise large">+₵${formatNumber(item.Change, 2)}</span>`;
    else if ( item.Change < 0 )
      change = `<span class="tag fall large">-₵${formatNumber(Math.abs(item.Change), 2)}</span>`;

    var amount = '';
    if ( item.Amount > 0 )
      amount = `<span class="tag new large">+${formatNumber(item.Amount, 0)}</span>`;
    else if ( item.Amount < 0 )
      amount = `<span class="tag even large">${formatNumber(item.Amount, 0)}</span>`;

    var id = '';
    if ( item.Type === 4 || item.Type === 5 || item.Type === 6 ) {
      id = `data-id="${item.RelatedId}"`;
    }

    var log = `<li class="${line} item_list item_log" ${id}>
                <div class="inner">₵${formatNumber(item.Balance, 2)}
                  <small class="grey">${formatTime(item.LogTime)}</small>
                  <span class="row"><small class="time">${item.Description}</small></span>
                </div>
                <span class="tags">
                  ${change}
                  ${amount}
                </span>
              </li>`;
    return log;
  }

  function renderCharacterDepth( chara ) {
    let depth = `<small class="raise">+${formatNumber(chara.Bids, 0)}</small><small class="fall">-${formatNumber(chara.Asks, 0)}</small><small class="even">${formatNumber(chara.Change, 0)}</small>`;
    return depth;
  }

  function renderCharacterTag( chara, item ) {
    let id = chara.Id;
    let flu = '--';
    let tclass = 'even';
    if ( chara.Fluctuation > 0 ) {
      tclass = 'raise';
      flu = `+${formatNumber(chara.Fluctuation * 100, 2)}%`;
    } else if ( chara.Fluctuation < 0 ) {
      tclass = 'fall';
      flu = `${formatNumber(chara.Fluctuation * 100, 2)}%`;
    }

    let tag = `<div class="tag ${tclass}" title="₵${formatNumber(chara.MarketValue, 0)} / ${formatNumber(chara.Total, 0)}">₵${formatNumber(chara.Current, 2)} ${flu}</div>`;
    return tag;
  }

  function renderBadge( item, withCrown, withNew, withLevel ) {
    let badge = '';

    if ( withLevel ) {
      badge = `<span class="badge level lv${item.Level}">lv${item.Level}</span>`;
    }
    if ( item.Type == 1 && withNew ) {
      badge += `<span class="badge new" title="+${formatNumber(item.Rate, 1)}新番加成剩余${item.Bonus}期">×${item.Bonus}</span>`;
    }
    if ( item.State > 0 && withCrown ) {
      badge += `<span class="badge crown" title="获得${item.State}次萌王">×${item.State}</span>`;
    }
    return badge;
  }

  function renderCharacter( item, type, even, showCancel ) {
    let line = 'line_odd';
    if ( even )
      line = 'line_even';
    let amount = `<small title="固定资产">${formatNumber(item.Sacrifices, 0)}</small>`;

    let tag = renderCharacterTag( item );
    let depth = renderCharacterDepth( item );
    let id = item.Id;
    if ( item.CharacterId )
      id = item.CharacterId;
    let time = item.LastOrder;
    let avatar = `<a href="/rakuen/topic/crt/${id}?trade=true" class="avatar l" target="right"><span class="avatarNeue avatarReSize32 ll" style="background-image:url('${normalizeAvatar(item.Icon)}')"></span></a>`;
    let cancel = '';
    if ( showCancel )
      cancel = `<span><small data-id="${id}" class="cancel_auction">[取消]</small></span>`;
    let badge = renderBadge( item, true, true, true );
    let chara;

    if ( type == 'auction' ) {
      chara = `<li class="${line} item_list" data-id="${id}">${avatar}<div class="inner">
<a href="/rakuen/topic/crt/${id}?trade=true" class="title avatar l" target="right">${item.Name}${badge}</a> <small class="grey">(+${item.Rate.toFixed(2)})</small>
<div class="row"><small class="time">${formatTime(time)}</small>
${cancel}</div></div>${tag}</li>`;
    } else if ( type == 'ico' ) {
      badge = renderBadge( item, false, false, false );
      chara = `<li class="${line} item_list" data-id="${id}">${avatar}<div class="inner">
<a href="/rakuen/topic/crt/${id}?trade=true" class="title avatar l" target="right">${item.Name}${badge}</a>
<div class="row"><small class="time">${formatTime(item.End)}</small><span><small>${formatNumber(item.State, 0)} / ${formatNumber(item.Total, 1)}</small></span>
</div></div><div class="tags tag lv1">ICO进行中</div></li>`;
    } else if ( type == 'temple' ) {
      let costs = '';
      if ( item.Assets - item.Sacrifices < 0 ) {
        costs = `<small class="fall" title="损耗">${item.Assets - item.Sacrifices}</small>
<span><small data-id="${id}" data-lv="${item.CharacterLevel}"  data-cost="${item.Sacrifices - item.Assets}" class="fill_costs">[补充]</small></span>`;
      }
      avatar = `<a href="/rakuen/topic/crt/${id}?trade=true" class="avatar l" target="right"><span class="avatarNeue avatarReSize32 ll" style="background-image:url('${normalizeAvatar(item.Cover)}')"></span></a>`;
      chara = `<li class="${line} item_list" data-id="${id}" data-lv="${item.CharacterLevel}">${avatar}<div class="inner">
<a href="/rakuen/topic/crt/${id}?trade=true" class="title avatar l" target="right">${item.Name}<span class="badge lv${item.CharacterLevel}">lv${item.CharacterLevel}</span></a> <small class="grey">(+${item.Rate.toFixed(2)})</small>
<div class="row"><small class="time" title="创建时间">${formatTime(item.Create)}</small><small title="固有资产 / 献祭值">${item.Assets} / ${item.Sacrifices}</small>${costs}</div></div>
<div class="tag lv${item.Level}">${item.Level}级圣殿</div></li>`;
    } else if ( item.CharacterId ) {
      let pre = caculateICO( item );
      badge = renderBadge( item, false, false, false );
      //let percent = formatNumber(item.Total / pre.Next * 100, 0);
      chara = `<li class="${line} item_list" data-id="${id}">${avatar}<div class="inner">
<a href="/rakuen/topic/crt/${id}?trade=true" class="title avatar l" target="right">${item.Name}${badge}</a> <small class="grey">(ICO进行中: lv${pre.Level})</small>
<div class="row"><small class="time">${formatTime(item.End)}</small><span><small>${formatNumber(item.Users, 0)}人 / ${formatNumber(item.Total, 1)} / ₵${formatNumber(pre.Price, 2)}</small></span>
${cancel}</div></div><div class="tags tag lv${pre.Level}">ICO进行中</div></li>`;
    } else {
      chara = `<li class="${line} item_list" data-id="${id}">${avatar}<div class="inner">
<a href="/rakuen/topic/crt/${id}?trade=true" class="title avatar l" target="right">${item.Name}${badge}</a> <small class="grey">(+${item.Rate.toFixed(2)} / ${formatNumber(item.Total, 0)} / ₵${formatNumber(item.MarketValue, 0)})</small>
<div class="row"><small class="time">${formatTime(item.LastOrder)}</small>${amount}<span title="买入 / 卖出 / 成交">${depth}</span>
${cancel}</div></div>${tag}</li>`;
    }

    return chara;
  }

  function fillCosts( id, lv, cost ) {
    closeDialog();
    let ItemsSetting = getItemsSetting();
    let supplyId = ItemsSetting.stardust ? ItemsSetting.stardust[ lv ] : '';
    let dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<div class="title" title="用一个角色的活股或固定资产,给另一个角色的圣殿消耗进行补充,目标人物的等级要小于或等于发动攻击圣殿的人物等级">星光碎片</div>
<div class="desc" style="display:none"></div>
<table align="center" width="98%" cellspacing="0" cellpadding="5" class="settings">
<tr><td>能源:<input id="supplyId" type="number" style="width:60px" value="${supplyId}"></td>
<td>目标:<input id="toSupplyId" type="number" style="width:60px" value="${id}"></td></tr>
<td>类型:<select id="isTemple" style="width:60px"><option value="false">活股</option><option value="true" selected="selected">塔股</option></select></td>
<td>数量:<input id="amount" type="number" style="width:60px" value="${cost}"></td></tr>
<tr><td><input class="inputBtn" value="充能" id="submit_stardust" type="submit"></td></tr>
</tbody></table>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>
</div>`;

    $__default['default']( 'body' ).append( dialog );
    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );
    $__default['default']( '#TB_overlay' ).on( 'click', closeDialog );
    if ( !supplyId ) {
      $__default['default']( '#TB_window .desc' ).text( `当前等级的能源角色id未设定,补充过一次之后会记住此等级的能源角色id` );
      $__default['default']( '#TB_window .desc' ).show();
    }
    $__default['default']( '#submit_stardust' ).on( 'click', () => {
      let supplyId = $__default['default']( '#supplyId' ).val();
      let toSupplyId = $__default['default']( '#toSupplyId' ).val();
      let isTemple = $__default['default']( '#isTemple' ).val();
      let amount = $__default['default']( '#amount' ).val();
      if ( supplyId ) {
        if ( !ItemsSetting.stardust )
          ItemsSetting.stardust = {};
        ItemsSetting.stardust[ lv ] = supplyId;
        setItemsSetting( ItemsSetting );
        postData( `magic/stardust/${supplyId}/${toSupplyId}/${amount}/${isTemple}`, null ).then( ( d ) => {
          closeDialog();
          if ( d.State == 0 )
            alert( d.Value );
          else
            alert( d.Message );
        } );
      } else
        alert( '角色id不能为空' );
    } );
  }

  let lastEven = false;

  function loadCharacterList( list, page, total, more, type, showCancel ) {
    let followList = getFollowList();
    $__default['default']( '#eden_tpc_list ul .load_more' ).remove();
    if ( page === 1 )
      $__default['default']( '#eden_tpc_list ul' ).html( '' );
    //console.log(list);
    for ( let i = 0; i < list.length; i++ ) {
      let item = list[ i ];
      //console.log(item);
      if ( type == 'balance' ) {
        let log = renderBalanceLog( item, lastEven );
        $__default['default']( '#eden_tpc_list ul' ).append( log );
      } else {
        let chara = renderCharacter( item, type, lastEven, showCancel );
        $__default['default']( '#eden_tpc_list ul' ).append( chara );
      }
      lastEven = !lastEven;
    }
    $__default['default']( '.cancel_auction' ).on( 'click', ( e ) => {
      //if (!confirm('确定取消关注?')) return;
      let id = $__default['default']( e.target ).data( 'id' ).toString();
      if ( type == 'chara' )
        followList.charas.splice( followList.charas.indexOf( id ), 1 );
      else if ( type == 'auction' )
        followList.auctions.splice( followList.auctions.indexOf( id ), 1 );
      setFollowList( followList );
      $__default['default']( `#eden_tpc_list li[data-id=${id}]` ).remove();
    } );

    $__default['default']( '.fill_costs' ).on( 'click', ( e ) => {
      let id = $__default['default']( e.target ).data( 'id' );
      let lv = $__default['default']( e.target ).data( 'lv' );
      let cost = $__default['default']( e.target ).data( 'cost' );
      fillCosts( id, lv, cost );
      $__default['default']( e.target ).remove();
    } );

    $__default['default']( '#eden_tpc_list .item_list' ).on( 'click', listItemClicked );
    if ( page != total && total > 0 ) {
      let loadMore = `<li class="load_more"><button id="loadMoreButton" class="load_more_button" data-page="${page + 1}">[加载更多]</button></li>`;
      $__default['default']( '#eden_tpc_list ul' ).append( loadMore );
      $__default['default']( '#loadMoreButton' ).on( 'click', function() {
        let page = $__default['default']( this ).data( 'page' );
        if ( more )
          more( page );
      } );
    } else {
      let noMore = '暂无数据';
      if ( total > 0 )
        noMore = '加载完成';

      $__default['default']( '#eden_tpc_list ul' ).append( `<li class="load_more sub">[${noMore}]</li>` );
    }
  }

  function loadFollowChara( page ) {
    let followList = getFollowList();
    let start = 50 * ( page - 1 );
    let ids = followList.charas.slice( start, start + 50 );
    let totalPages = Math.ceil( followList.charas.length / 50 );
    postData( 'chara/list', ids ).then( ( d ) => {
      if ( d.State === 0 ) {
        loadCharacterList( d.Value, page, totalPages, loadFollowChara, 'chara', true );
      }
    } );
  }

  function loadMyICO( page ) {
    getData( `chara/user/initial/0/${page}/50` ).then( ( d ) => {
      if ( d.State == 0 ) {
        loadCharacterList( d.Value.Items, d.Value.CurrentPage, d.Value.TotalPages, loadMyICO, 'ico', false );
      }
    } );
  }

  function loadMyTemple( page ) {
    getData( `chara/user/temple/0/${page}/50` ).then( ( d ) => {
      if ( d.State == 0 ) {
        loadCharacterList( d.Value.Items, d.Value.CurrentPage, d.Value.TotalPages, loadMyTemple, 'temple', false );
        if ( page == 1 ) {
          $__default['default']( '#eden_tpc_list ul' ).prepend( `<li id="lostTemple" class="line_odd item_list" style="text-align: center;">[查看受损圣殿]</li>` );
          $__default['default']( '#lostTemple' ).on( 'click', function() {
            $__default['default']( '#eden_tpc_list ul' ).html( '' );
            loadLostTemple( 1 );
          } );
        }
      }
    } );
  }

  function loadLostTemple( page ) {
    let lostTemples = [];
    getData( `chara/user/temple/0/${page}/500` ).then( ( d ) => {
      if ( d.State == 0 ) {
        for ( let i = 0; i < d.Value.Items.length; i++ ) {
          if ( d.Value.Items[ i ].Assets - d.Value.Items[ i ].Sacrifices < 0 )
            lostTemples.push( d.Value.Items[ i ] );
        }
        loadCharacterList( lostTemples, 2, 2, loadLostTemple, 'temple', false );
      }
      if ( page < d.Value.TotalPages ) {
        page++;
        loadLostTemple( page );
      }
    } );
  }

  function loadScratch() {
    let ItemsSetting = getItemsSetting();
    $__default['default']( '#eden_tpc_list ul' ).html( '' );
    $__default['default']( '#eden_tpc_list ul' ).append( `<li class="line_odd item_list" style="text-align: center;">[刮刮乐]</li>` );
    let scratch_results = [],
      scratch_ids = [],
      chaosCube_results = [],
      chaosCube_ids = [];
    scratch();

    function scratch() {
      getData( 'event/scratch/bonus2' ).then( ( d ) => {
        if ( d.State == 0 ) {
          for ( let i = 0; i < d.Value.length; i++ ) {
            scratch_results.push( d.Value[ i ] );
            scratch_ids.push( d.Value[ i ].Id );
          }
          if ( !d.Value.length ) {
            scratch_results.push( d.Value );
            scratch_ids.push( d.Value.Id );
          }
          scratch();
        } else {
          postData( 'chara/list', scratch_ids ).then( ( d ) => {
            for ( let i = 0; i < d.Value.length; i++ ) {
              d.Value[ i ].Sacrifices = scratch_results[ i ].Amount;
              d.Value[ i ].Current = scratch_results[ i ].SellPrice;
            }
            loadCharacterList( d.Value, 2, 2, loadScratch, 'chara', false );
            $__default['default']( '#eden_tpc_list ul' ).append( `<li class="line_odd item_list" style="text-align: center;">[混沌魔方]</li>` );
            chaosCube();
          } );
        }
      } );
    }

    function chaosCube() {
      let templeId = ItemsSetting.chaosCube;
      if ( templeId ) {
        postData( `magic/chaos/${templeId}`, null ).then( ( d ) => {
          console.log( d );
          if ( d.State == 0 ) {
            for ( let i = 0; i < d.Value.length; i++ ) {
              chaosCube_results.push( d.Value[ i ] );
              chaosCube_ids.push( d.Value[ i ].Id );
            }
            if ( !d.Value.length ) {
              chaosCube_results.push( d.Value );
              chaosCube_ids.push( d.Value.Id );
            }
            chaosCube();
          } else {
            if ( d.Message != '今日已超过使用次数限制或资产不足。' ) {
              alert( d.Message );
              chaosCube();
            } else
              postData( 'chara/list', chaosCube_ids ).then( ( d ) => {
                for ( let i = 0; i < d.Value.length; i++ ) {
                  d.Value[ i ].Sacrifices = chaosCube_results[ i ].Amount;
                  d.Value[ i ].Current = chaosCube_results[ i ].SellPrice;
                }
                loadCharacterList( d.Value, 2, 2, loadScratch, 'chara', false );
              } );
          }
        } );
      } else
        alert( '未设置施放混沌魔方的圣殿,请先在角色圣殿施放一次混沌魔方即可完成预设' );
    }
  }

  function loadMagic() {
    closeDialog();
    let ItemsSetting = getItemsSetting();
    let templeId = ItemsSetting.chaosCube || '';
    let monoId = ItemsSetting.guidepost ? ItemsSetting.guidepost.monoId : '';
    let toMonoId = ItemsSetting.guidepost ? ItemsSetting.guidepost.toMonoId : '';
    let dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<table align="center" width="98%" cellspacing="0" cellpadding="5" class="settings">
<tr><td title="消耗圣殿10点固定资产,获取随机角色10-100股随机数量">混沌魔方</td>
<td>炮塔:<input id="chaosCube" type="number" style="width:60px" value="${templeId}"></td><td></td>
<td><input class="inputBtn" value="发射" id="submit_chaosCube" type="submit"></td></tr>
<tr><td title="消耗圣殿100点固定资产,获取指定股票10-100股随机数量,目标人物的等级要小于或等于发动攻击圣殿的人物等级">虚空道标</td>
<td>炮塔:<input id="monoId" type="number" style="width:60px" value="${monoId}"></td>
<td>目标:<input id="toMonoId" type="number" style="width:60px" value="${toMonoId}"></td>
<td><input class="inputBtn" value="发射" id="submit_guidepost" type="submit"></td></tr>
<tr><td title="用一个角色的活股或固定资产,给另一个角色的圣殿消耗进行补充,目标人物的等级要小于或等于发动攻击圣殿的人物等级">星光碎片</td>
<td>能源:<input id="supplyId" type="number" style="width:60px"></td>
<td>目标:<input id="toSupplyId" type="number" style="width:60px"></td></tr>
<td></td><td>类型:<select id="isTemple" style="width:60px"><option value="false">活股</option><option value="true" selected="selected">塔股</option></select></td>
<td>数量:<input id="amount" type="number" style="width:60px" value="100"></td>
<td><input class="inputBtn" value="充能" id="submit_stardust" type="submit"></td></tr>
</tbody></table>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>
</div>`;

    $__default['default']( 'body' ).append( dialog );
    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );
    $__default['default']( '#TB_overlay' ).on( 'click', closeDialog );
    $__default['default']( '#submit_chaosCube' ).on( 'click', () => {
      let templeId = $__default['default']( '#chaosCube' ).val();
      ItemsSetting.chaosCube = templeId;
      setItemsSetting( ItemsSetting );
      postData( `magic/chaos/${templeId}`, null ).then( ( d ) => {
        closeDialog();
        console.log( d );
        if ( d.State == 0 ) {
          $__default['default']( '#eden_tpc_list ul' ).html( '' );
          $__default['default']( '#eden_tpc_list ul' ).append( `<li class="line_odd item_list" style="text-align: center;">[混沌魔方]</li>` );
          let Id = d.Value.Id;
          let Amount = d.Value.Amount;
          let SellPrice = d.Value.SellPrice;
          postData( 'chara/list', [ Id ] ).then( ( d ) => {
            for ( let i = 0; i < d.Value.length; i++ ) {
              d.Value[ i ].Sacrifices = Amount;
              d.Value[ i ].Current = SellPrice;
            }
            loadCharacterList( d.Value, 2, 2, loadScratch, 'chara', false );
          } );
        } else
          alert( d.Message );
      } );
    } );
    $__default['default']( '#submit_guidepost' ).on( 'click', () => {
      let monoId = $__default['default']( '#monoId' ).val();
      let toMonoId = $__default['default']( '#toMonoId' ).val();
      ItemsSetting.guidepost = {
        "monoId": monoId,
        "toMonoId": toMonoId
      };
      setItemsSetting( ItemsSetting );
      postData( `magic/guidepost/${monoId}/${toMonoId}`, null ).then( ( d ) => {
        closeDialog();
        console.log( d );
        if ( d.State == 0 ) {
          $__default['default']( '#eden_tpc_list ul' ).html( '' );
          $__default['default']( '#eden_tpc_list ul' ).append( `<li class="line_odd item_list" style="text-align: center;">[虚空道标]</li>` );
          let Id = d.Value.Id;
          let Amount = d.Value.Amount;
          let SellPrice = d.Value.SellPrice;
          postData( 'chara/list', [ Id ] ).then( ( d ) => {
            for ( let i = 0; i < d.Value.length; i++ ) {
              d.Value[ i ].Sacrifices = Amount;
              d.Value[ i ].Current = SellPrice;
            }
            loadCharacterList( d.Value, 2, 2, loadScratch, 'chara', false );
          } );
        } else
          alert( d.Message );
      } );
    } );
    $__default['default']( '#submit_stardust' ).on( 'click', () => {
      let supplyId = $__default['default']( '#supplyId' ).val();
      let toSupplyId = $__default['default']( '#toSupplyId' ).val();
      let isTemple = $__default['default']( '#isTemple' ).val();
      let amount = $__default['default']( '#amount' ).val();
      postData( `magic/stardust/${supplyId}/${toSupplyId}/${amount}/${isTemple}`, null ).then( ( d ) => {
        closeDialog();
        console.log( d );
        if ( d.State == 0 ) {
          alert( d.Value );
          $__default['default']( '#eden_tpc_list ul' ).html( '' );
          $__default['default']( '#eden_tpc_list ul' ).append( `<li class="line_odd item_list" style="text-align: center;">[星光碎片]</li>` );
          postData( 'chara/list', [ supplyId, toSupplyId ] ).then( ( d ) => {
            loadCharacterList( d.Value, 2, 2, loadScratch, 'chara', false );
          } );
        } else
          alert( d.Message );
      } );
    } );
  }

  let charas_list = [];

  function set_charas_list( lst ) {
    charas_list = lst;
  }

  function loadTemperaryList( page ) {
    let start = 50 * ( page - 1 );
    let ids = charas_list.slice( start, start + 50 );
    console.log( ids );
    let totalPages = Math.ceil( charas_list.length / 50 );
    postData( 'chara/list', ids ).then( ( d ) => {
      if ( d.State === 0 ) {
        loadCharacterList( d.Value, page, totalPages, loadTemperaryList, 'chara', false );
      }
    } );
  }

  async function autoJoinICO( icoList ) {
    for ( let i = 0; i < icoList.length; i++ ) {
      let charaId = icoList[ i ].CharacterId;
      await getData( `chara/${charaId}` ).then( ( d ) => {
        if ( d.State == 0 ) {
          let offer = 5000;
          let Id = d.Value.Id;
          if ( d.Value.Total < 100000 && d.Value.Users < 15 ) {
            getData( `chara/initial/${Id}` ).then( ( d ) => {
              if ( d.State == 1 ) {
                postData( `chara/join/${Id}/${offer}`, null ).then( ( d ) => {
                  if ( d.State === 0 ) {
                    console.log( `#${charaId} 追加注资成功。` );
                    $__default['default']( `#eden_tpc_list li[data-id=${charaId}] .row` ).append( `<small class="raise">+${offer}</small>` );
                  }
                } );
              }
            } );
          }
        }
      } );
    }
  }

  async function joinAuctions( ids ) {
    for ( let i = 0; i < ids.length; i++ ) {
      let Id = ids[ i ];
      await postData( 'chara/auction/list', [ Id ] ).then( ( d ) => {
        let myAuctionAmount = 0;
        if ( d.Value.length )
          myAuctionAmount = d.Value[ 0 ].Amount;
        if ( myAuctionAmount ) {
          let myAuction = `<span class="my_auction auction_tip" title="出价 / 数量">₵${formatNumber(d.Value[0].Price, 2)} / ${myAuctionAmount}</span>`;
          $__default['default']( `.item_list[data-id=${Id}] .time` ).after( myAuction );
        } else {
          getData( `chara/user/${Id}/tinygrail/false` ).then( ( d ) => {
            let price = Math.ceil( d.Value.Price * 100 ) / 100;
            let amount = 1;
            postData( `chara/auction/${Id}/${price}/${amount}`, null ).then( ( d ) => {
              if ( d.State == 0 ) {
                let myAuction = `<span class="my_auction auction_tip" title="出价 / 数量">₵${price} / ${amount}</span>`;
                $__default['default']( `.item_list[data-id=${Id}] .time` ).after( myAuction );
              } else {
                console.log( d.Message );
              }
            } );
          } );
        }
      } );
    }
  }

  async function loadValhalla( ids ) {
    for ( let i = 0; i < ids.length; i++ ) {
      let Id = ids[ i ];
      await getData( `chara/user/${Id}/tinygrail/false` ).then( ( d ) => {
        let valhalla = `<small class="even" title="拍卖底价 / 拍卖数量">₵${formatNumber(d.Value.Price, 2)} / ${d.Value.Amount}</small>`;
        $__default['default']( `.cancel_auction[data-id=${Id}]` ).before( valhalla );
      } );
    }
  }

  function loadUserAuctions( d ) {
    d.Value.forEach( ( a ) => {
      if ( a.State != 0 ) {
        let userAuction = `<span class="user_auction auction_tip" title="竞拍人数 / 竞拍数量">${formatNumber(a.State, 0)} / ${formatNumber(a.Type, 0)}</span>`;
        $__default['default']( `.item_list[data-id=${a.CharacterId}] .time` ).after( userAuction );
        $__default['default']( `#auctionHistoryButton` ).before( userAuction );
        $__default['default']( '#TB_window.dialog .desc' ).append( userAuction );
      }
      if ( a.Price != 0 ) {
        let myAuction = `<span class="my_auction auction_tip" title="出价 / 数量">₵${formatNumber(a.Price, 2)} / ${formatNumber(a.Amount, 0)}</span>`;
        $__default['default']( `.item_list[data-id=${a.CharacterId}] .time` ).after( myAuction );
        $__default['default']( `#auctionHistoryButton` ).before( myAuction );
        $__default['default']( '#TB_window.dialog .desc' ).append( myAuction );
      }
    } );
  }

  function loadFollowAuction( page ) {
    let followList = getFollowList();
    let start = 20 * ( page - 1 );
    let ids = followList.auctions.slice( start, start + 20 );
    let totalPages = Math.ceil( followList.auctions.length / 20 );
    postData( 'chara/list', ids ).then( ( d ) => {
      if ( d.State === 0 ) {
        loadCharacterList( d.Value, page, totalPages, loadFollowAuction, 'auction', true );
        postData( 'chara/auction/list', ids ).then( ( d ) => {
          loadUserAuctions( d );
        } );
        loadValhalla( ids );
      }
    } );
  }

  const dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<div class="bibeBox" style="padding:10px">
<label>在超展开左边创建角色列表 请输入角色url或id,如 https://bgm.tv/character/29282 或 29282,一行一个</label>
<textarea rows="10" class="quick" name="urls"></textarea>
<input class="inputBtn" value="创建列表" id="submit_list" type="submit" style="padding: 3px 5px;">
<input class="inputBtn" value="关注角色" id="add_follow" type="submit" style="padding: 3px 5px;">
<input class="inputBtn" value="关注竞拍" id="add_auction" type="submit" style="padding: 3px 5px;">
<input class="inputBtn" value="参与竞拍" id="join_auction" type="submit" style="padding: 3px 5px;">
<input class="inputBtn" value="参与ICO" id="join_ico" type="submit" style="padding: 3px 5px;">
</div>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>
</div>`;

  function get_charas_list() {
    let charas_list = [];
    let charas = $__default['default']( '.bibeBox textarea' ).val().split( '\n' );
    for ( let i = 0; i < charas.length; i++ ) {
      try {
        let charaId = charas[ i ].match( /(character\/|crt\/)?(\d+)/ )[ 2 ];
        charas_list.push( charaId );
      } catch ( e ) {}  }
    set_charas_list( charas_list );
  }

  function creatTemporaryList( page ) {
    closeDialog();

    $__default['default']( 'body' ).append( dialog );
    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );
    $__default['default']( '#TB_overlay' ).on( 'click', closeDialog );
    $__default['default']( '#submit_list' ).on( 'click', () => {
      get_charas_list();
      loadTemperaryList( 1 );
      closeDialog();
    } );
    $__default['default']( '#add_follow' ).on( 'click', () => {
      let charas_list = get_charas_list();
      for ( let i = 0; i < charas_list.length; i++ ) {
        let followList = getFollowList();
        let charaId = charas_list[ i ].toString();
        if ( followList.charas.includes( charaId ) ) {
          followList.charas.splice( followList.charas.indexOf( charaId ), 1 );
          followList.charas.unshift( charaId );
        } else {
          followList.charas.unshift( charaId );
        }
        setFollowList( followList );
      }
      loadFollowChara( 1 );
      closeDialog();
    } );

    $__default['default']( '#add_auction' ).on( 'click', () => {
      get_charas_list();
      for ( let i = 0; i < charas_list.length; i++ ) {
        let followList = getFollowList();
        let charaId = charas_list[ i ].toString();
        if ( followList.auctions.includes( charaId ) ) {
          followList.auctions.splice( followList.auctions.indexOf( charaId ), 1 );
          followList.auctions.unshift( charaId );
        } else {
          followList.auctions.unshift( charaId );
        }
        setFollowList( followList );
      }
      loadFollowAuction( 1 );
      closeDialog();
    } );

    $__default['default']( '#join_auction' ).on( 'click', () => {
      get_charas_list();
      $__default['default']( '#eden_tpc_list ul' ).html( '' );
      loadTemperaryList( 1 );
      joinAuctions( charas_list );
      closeDialog();
    } );

    $__default['default']( '#join_ico' ).on( 'click', () => {
      get_charas_list();
      postData( 'chara/list', charas_list ).then( ( d ) => {
        autoJoinICO( d.Value );
        loadTemperaryList( 1 );
        closeDialog();
      } );
    } );
  }

  function loadBalance() {
    closeDialog();
    let dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<table align="center" width="98%" cellspacing="0" cellpadding="5" class="settings">
<tr><td>类型:<select id="balanceType" style="width:100px">
<option value="0" selected="selected">全部</option>
<option value="18">魔法道具</option>
<option value="1">彩票刮刮乐</option>
<option value="2">参与ICO</option>
<option value="3">ICO退款</option>
<option value="13">ICO结果</option>
<option value="4">买入委托</option>
<option value="5">取消买入</option>
<option value="6">卖出委托</option>
<option value="8">取消卖出</option>
<option value="7">交易印花税</option>
<option value="9">资产重组</option>
<option value="10">参与竞拍</option>
<option value="11">修改竞拍</option>
<option value="12">竞拍结果</option>
<option value="14">个人所得税</option>
<option value="16">红包</option>
</select></td>
<td>第<input id="page" type="number" style="width:30px" value="1">页</td>
<td>每页<input id="amount" type="number" style="width:50px" value="1000">条</td>
<td><input class="inputBtn" value="查询" id="submit_search" type="submit"></td></tr>
</tbody></table>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>
</div>`;
    $__default['default']( 'body' ).append( dialog );
    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );
    $__default['default']( '#TB_overlay' ).on( 'click', closeDialog );
    $__default['default']( '#submit_search' ).on( 'click', () => {
      let Type = $__default['default']( '#balanceType' ).val();
      let page = $__default['default']( '#page' ).val();
      let amount = $__default['default']( '#amount' ).val();
      let Logs = [];
      getData( `chara/user/balance/${page}/${amount}`).then( ( d ) => {
        closeDialog();
        if ( d.State == 0 ) {
          for ( let i = 0; i < d.Value.Items.length; i++ ) {
            if ( d.Value.Items[ i ].Type == Type || Type == 0 )
              Logs.push( d.Value.Items[ i ] );
          }
          loadCharacterList( Logs, 1, 1, loadBalance, 'balance', false );
          $__default['default']( '#eden_tpc_list ul li' ).on( 'click', function( e ) {
            var id = $__default['default']( e.target ).data( 'id' );
            if ( id == null ) {
              var result = $__default['default']( e.target ).find( 'small.time' ).text().match( /#(\d+)/ );
              if ( result && result.length > 0 )
                id = result[ 1 ];
            }

            if ( id != null && id.length > 0 ) {
              if ( parent.window.innerWidth < 1200 ) {
                $__default['default']( parent.document.body ).find( "#split #listFrameWrapper" ).animate( {
                  left: '-450px'
                } );
              }
              window.open( `/rakuen/topic/crt/${id}?trade=true`, 'right' );
            }
          } );
        }
      } );
    } );
  }

  function loadAutoBuild( page ) {
    let autoTempleList = getAutoTempleList$1();
    autoBuildTemple( autoTempleList );
    let charas = [];
    for ( let i = 0; i < autoTempleList.length; i++ )
      charas.push( autoTempleList[ i ].charaId );
    let start = 50 * ( page - 1 );
    let ids = charas.slice( start, start + 50 );
    let totalPages = Math.ceil( charas.length / 50 );
    postData( 'chara/list', ids ).then( ( d ) => {
      if ( d.State === 0 ) {
        loadCharacterList( d.Value, page, totalPages, loadAutoBuild, 'chara', false );
      }
    } );
  }

  function loadAutoFillICO( page ) {
    let fillicoList = getFillICOList();
    let charas = [];
    for ( let i = 0; i < fillicoList.length; i++ )
      charas.push( fillicoList[ i ].charaId );
    let start = 50 * ( page - 1 );
    let ids = charas.slice( start, start + 50 );
    let totalPages = Math.ceil( charas.length / 50 );
    postData( 'chara/list', ids ).then( ( d ) => {
      if ( d.State === 0 ) {
        loadCharacterList( d.Value, page, totalPages, loadAutoBuild, 'chara_ico', false );
      }
    } );
  }

  function loadHelperMenu() {
    let item = `<li><a href="#" id="helperMenu" class="top">助手</a>
<ul>
<li><a href="#" id="temporaryList">临时列表</a></li>
<li><a href="#" id="followChara">关注角色</a></li>
<li><a href="#" id="followAuction">关注竞拍</a></li>
<li><a href="#" id="myICO">我的ICO</a></li>
<li><a href="#" id="myTemple">我的圣殿</a></li>
<li><a href="#" id="scratch">抽奖</a></li>
<li><a href="#" id="magic">魔法道具</a></li>
<li><a href="#" id="balance">资金日志分类</a></li>
<li><a href="#" id="sell">卖出</a></li>
<li><a href="#" id="autoBuild">自动建塔</a></li>
<li><a href="#" id="autoICO">自动补款</a></li>
<li><a href="#" id="cancelBids">取消买单</a></li>
<li><a href="#" id="settings">设置</a></li>
</ul>
</li>`;
    $__default['default']( '.timelineTabs' ).append( item );

    $__default['default']( '#followChara' ).on( 'click', function() {
      menuItemClicked( loadFollowChara );
    } );

    $__default['default']( '#followAuction' ).on( 'click', function() {
      menuItemClicked( loadFollowAuction );
    } );

    $__default['default']( '#myICO' ).on( 'click', function() {
      menuItemClicked( loadMyICO );
    } );

    $__default['default']( '#myTemple' ).on( 'click', function() {
      menuItemClicked( loadMyTemple );
    } );

    $__default['default']( '#balance' ).on( 'click', function() {
      menuItemClicked( loadBalance );
    } );

    $__default['default']( '#autoBuild' ).on( 'click', function() {
      menuItemClicked( loadAutoBuild );
    } );

    $__default['default']( '#autoICO' ).on( 'click', function() {
      menuItemClicked( loadAutoFillICO );
    } );

    $__default['default']( '#temporaryList' ).on( 'click', function() {
      menuItemClicked( creatTemporaryList );
    } );

    $__default['default']( '#scratch' ).on( 'click', function() {
      menuItemClicked( loadScratch );
    } );

    $__default['default']( '#magic' ).on( 'click', function() {
      menuItemClicked( loadMagic );
    } );

    $__default['default']( '#sell' ).on( 'click', function() {
      menuItemClicked( sellOut );
    } );

    $__default['default']( '#cancelBids' ).on( 'click', function() {
      menuItemClicked( cancelBids );
    } );

    $__default['default']( '#settings' ).on( 'click', function() {
      menuItemClicked( openSettings );
    } );
  }

  function showGallery() {
    let settings = getSettings();
    if ( settings.gallery == 'on' ) {
      let index = 0;
      $__default['default']( 'body' ).on( 'keydown', function( e ) {
        switch ( event.keyCode ) {
          case 37:
            closeDialog();
            $__default['default']( `.item .card` )[ index - 1 ].click();
            break;
          case 39:
            closeDialog();
            $__default['default']( `.item .card` )[ index + 1 ].click();
            break;
        }
      } );
      $__default['default']( 'body' ).on( 'touchstart', '#TB_window.temple', function( e ) {
        let touch = e.originalEvent;
        let startX = touch.changedTouches[ 0 ].pageX;
        $__default['default']( this ).on( 'touchmove', function( e ) {
          e.preventDefault();
          touch = e.originalEvent.touches[ 0 ] || e.originalEvent.changedTouches[ 0 ];
          if ( touch.pageX - startX > 20 ) { //向左
            closeDialog();
            $__default['default']( `.item .card` )[ index - 1 ].click();
            $__default['default']( this ).off( 'touchmove' );
          } else if ( touch.pageX - startX < -20 ) { //向右
            closeDialog();
            $__default['default']( `.item .card` )[ index + 1 ].click();
            $__default['default']( this ).off( 'touchmove' );
          }      } );
      } ).on( 'touchend', function() {
        $__default['default']( this ).off( 'touchmove' );
      } );
      setInterval( function() {
        $__default['default']( `.item .card` ).on( 'click', ( e ) => {
          index = $__default['default']( `.item .card` ).index( e.currentTarget );
          gallery_mode = true;
        } );
      }, 1000 );
    }
  }

  function showHideGrailBox() {
    let settings = getSettings();
    let config = settings.hide_grail;
    if ( config == 'on' ) {
      $__default['default']( '#grail' ).hide();
      setTimeout( () => {
        $__default['default']( '#pager1' ).hide();
      }, 500 );
    }
  }

  function cancelAuction( chara ) {
    let message = '确定取消竞拍?';
    let Day = new Date().getDay();
    if ( Day == 6 )
      message = '周六取消竞拍将收取20%税,确定取消竞拍?';
    if ( !confirm( message ) )
      return;
    $__default['default']( "#TB_window .loading" ).show();
    $__default['default']( '#TB_window .label' ).hide();
    $__default['default']( "#TB_window .desc" ).hide();
    $__default['default']( "#TB_window .trade" ).hide();
    getData( `chara/user/auction/1/100` ).then( ( d ) => {
      let id = 0;
      for ( let i = 0; i < d.Value.Items.length; i++ ) {
        if ( chara.Id == d.Value.Items[ i ].CharacterId ) {
          id = d.Value.Items[ i ].Id;
          break;
        }
      }
      if ( id ) {
        postData( `chara/auction/cancel/${id}`, null ).then( ( d ) => {
          $__default['default']( "#TB_window .loading" ).hide();
          $__default['default']( '#TB_window .label' ).show();
          $__default['default']( "#TB_window .desc" ).show();
          $__default['default']( "#TB_window .trade" ).show();
          if ( d.State == 0 ) {
            $__default['default']( '#TB_window .trade' ).hide();
            $__default['default']( '#TB_window .label' ).hide();
            $__default['default']( '#TB_window .desc' ).text( '取消竞拍成功' );
          } else
            alert( d.Message );
        } );
      } else {
        $__default['default']( "#TB_window .loading" ).hide();
        $__default['default']( '#TB_window .desc' ).text( '未找到竞拍角色' );
      }
    } );
  }

  function bidAuction( chara ) {
    $__default['default']( "#TB_window .loading" ).show();
    $__default['default']( '#TB_window .label' ).hide();
    $__default['default']( "#TB_window .desc" ).hide();
    $__default['default']( "#TB_window .trade" ).hide();
    let price = $__default['default']( '.trade.auction .price' ).val();
    let amount = $__default['default']( '.trade.auction .amount' ).val();
    postData( `chara/auction/${chara.Id}/${price}/${amount}`, null ).then( ( d ) => {
      $__default['default']( "#TB_window .loading" ).hide();
      $__default['default']( '#TB_window .label' ).show();
      $__default['default']( "#TB_window .desc" ).show();
      $__default['default']( "#TB_window .trade" ).show();
      if ( d.State == 0 ) {
        let message = d.Value;
        $__default['default']( '#TB_window .trade' ).hide();
        $__default['default']( '#TB_window .label' ).hide();
        $__default['default']( '#TB_window .desc' ).text( message );
      } else {
        alert( d.Message );
      }
    } );
  }

  function openAuctionDialog( chara, auction ) {
    let auction_num = chara.State;
    if ( getSettings$1().auction_num == 'one' )
      auction_num = 1;
    let price = Math.ceil( chara.Price * 100 ) / 100;
    let total = formatNumber( price * chara.State, 2 );
    let dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<div class="title" title="拍卖底价 / 竞拍数量 / 流通股份">股权拍卖 - #${chara.Id} 「${chara.Name}」 ₵${formatNumber(chara.Price, 2)} / ${chara.State} / ${chara.Total}</div>
<div class="desc">
<button id="fullfill_auction" class="text_button" title="当竞拍数量未满时补满数量">[补满]</button>
<button id="change_amount" class="text_button" title="按修改后的价格确定数量,保持总价不变">[改量]</button>
<button id="change_price" class="text_button" title="按修改后的数量确定价格,保持总价不变">[改价]</button>
</div><div class="label">
<span class="input">价格</span><span class="input">数量</span><span class="total">合计 -₵${total}</span>
</div><div class="trade auction">
<input class="price" type="number" style="width: 100px" min="${price}" value="${price}">
<input class="amount" type="number" style="width: 100px" min="1" max="${chara.State}" value="${auction_num}">
<button id="bidAuctionButton" class="active">确定</button><button id="cancelAuctionButton" style="display: none">取消竞拍</button></div>
<div class="loading" style="display:none"></div>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>`;
    $__default['default']( 'body' ).append( dialog );
    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );

    $__default['default']( '.assets_box .auction_tip' ).remove();
    loadUserAuctions( auction );

    $__default['default']( '#cancelAuctionButton' ).on( 'click', function() {
      cancelAuction( chara );
    } );
    $__default['default']( '#bidAuctionButton' ).on( 'click', function() {
      bidAuction( chara );
    } );

    if ( !auction.Value.length ) {
      auction.Value = [ {
        "Price": 0,
        "Amount": 0,
        "Type": 0,
        "State": 0
      } ];
    }

    if ( auction.Value[ 0 ].Price ) {
      $__default['default']( '.trade.auction .price' ).val( auction.Value[ 0 ].Price );
      $__default['default']( '.trade.auction .amount' ).val( auction.Value[ 0 ].Amount );
      let total = formatNumber( auction.Value[ 0 ].Price * auction.Value[ 0 ].Amount, 2 );
      $__default['default']( "#TB_window .label .total" ).text( `合计 -₵${total}` );
      $__default['default']( '#cancelAuctionButton' ).show();
    }

    $__default['default']( '#TB_window .auction input' ).on( 'keyup', () => {
      let price = $__default['default']( '.trade.auction .price' ).val();
      let amount = $__default['default']( '.trade.auction .amount' ).val();
      let total = formatNumber( price * amount, 2 );
      $__default['default']( "#TB_window .label .total" ).text( `合计 -₵${total}` );
    } );
    $__default['default']( '#fullfill_auction' ).on( 'click', function() {
      let total_auction = chara.State;
      let amount = total_auction - auction.Value[ 0 ].Type + auction.Value[ 0 ].Amount;
      let price = Math.ceil( chara.Price * 100 ) / 100;
      $__default['default']( '.trade.auction .price' ).val( price );
      $__default['default']( '.trade.auction .amount' ).val( amount );
      $__default['default']( "#TB_window .label .total" ).text( `合计 -₵${formatNumber(price * amount, 2)}` );
    } );
    $__default['default']( '#change_amount' ).on( 'click', function() {
      let price = parseFloat( $__default['default']( '.trade.auction .price' ).val() );
      let total = auction.Value[ 0 ].Price * auction.Value[ 0 ].Amount;
      let amount = Math.ceil( total / price );
      $__default['default']( '.trade.auction .amount' ).val( amount );
      $__default['default']( "#TB_window .label .total" ).text( `合计 -₵${formatNumber(price * amount, 2)}` );
    } );
    $__default['default']( '#change_price' ).on( 'click', function() {
      let amount = parseInt( $__default['default']( '.trade.auction .amount' ).val() );
      let total = auction.Value[ 0 ].Price * auction.Value[ 0 ].Amount;
      let price = Math.ceil( total / amount * 100 ) / 100;
      $__default['default']( '.trade.auction .price' ).val( price );
      $__default['default']( "#TB_window .label .total" ).text( `合计 -₵${formatNumber(price * amount, 2)}` );
    } );
  }

  function showTopWeek() {
    getData( `chara/topweek` ).then( ( d ) => {
      let totalExtra = 0,
        totalPeople = 0;
      for ( let i = 0; i < d.Value.length; i++ ) {
        totalExtra += d.Value[ i ].Extra;
        totalPeople += d.Value[ i ].Type;
      }
      console.log( totalExtra + '/' + totalPeople + '=' + totalExtra / totalPeople );
      $__default['default']( '#topWeek .auction_button' ).hide();
      for ( let i = 0; i < d.Value.length; i++ ) {
        let score = d.Value[ i ].Extra + d.Value[ i ].Type * totalExtra / totalPeople;
        let tag = $__default['default']( `#topWeek .assets .item` )[ i ].querySelector( '.tag' );
        $__default['default']( tag ).attr( 'title', '综合得分:' + formatNumber( score, 2 ) );
        let average = ( d.Value[ i ].Extra + d.Value[ i ].Price * d.Value[ i ].Sacrifices ) / d.Value[ i ].Assets;
        let buff = $__default['default']( `#topWeek .assets .item` )[ i ].querySelector( '.buff' );
        $__default['default']( buff ).attr( 'title', '平均拍价:' + formatNumber( average, 2 ) );
        let charaId = d.Value[ i ].CharacterId;
        let auction_button = $__default['default']( `<div class="name auction" data-id="${charaId}">
<span title="竞拍人数 / 竞拍数量 / 拍卖总数">${d.Value[i].Type} / ${d.Value[i].Assets} / ${d.Value[i].Sacrifices}</span></div>` );
        $__default['default']( $__default['default']( `#topWeek .assets .item` )[ i ] ).append( auction_button );
        let chara = {
          "Id": d.Value[ i ].CharacterId,
          "Name": d.Value[ i ].CharacterName,
          "Price": d.Value[ i ].Price,
          "State": d.Value[ i ].Sacrifices,
          "Total": 0
        };
        auction_button.on( 'click', () => {
          postData( 'chara/auction/list', [ charaId ] ).then( ( d ) => {
            openAuctionDialog( chara, d );
          } );
        } );
      }
    } );
  }

  function fixAuctions( chara ) {
    getData( `chara/user/${chara.Id}/tinygrail/false` ).then( ( d ) => {
      chara.Price = d.Value.Price;
      chara.State = d.Value.Amount;
      let button = `<button id="auctionButton2" class="text_button">[萌王投票]</button>`;
      if ( d.State == 0 && d.Value.Amount > 0 )
        button = `<button id="auctionButton2" class="text_button">[参与竞拍]</button>`;
      $__default['default']( '#buildButton' ).before( button );
      $__default['default']( '#auctionButton' ).hide();
      postData( 'chara/auction/list', [ chara.Id ] ).then( ( d ) => {
        loadUserAuctions( d );
        $__default['default']( '#auctionButton2' ).on( 'click', () => {
          openAuctionDialog( chara, d );
        } );
      } );
    } );
  }

  function openHistoryDialog( chara, page ) {
    let dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<div class="title">上${page}周拍卖结果 - #${chara.Id} 「${chara.Name}」 ₵${formatNumber(chara.Current, 2)} / ${formatNumber(chara.Total, 0)}</div>
<div class="desc" style="display:none"></div>
<div class="result" style="display:none; max-height: 500px; overflow: auto;"></div>
<div class="page_inner">
<a id="nextweek" class="p" style="display:none; float: left;margin-bottom: 5px;margin-left: 50px;">后一周</a>
<a id="lastweek" class="p" style="display:none; float: right;margin-bottom: 5px;margin-right: 50px;">前一周</a>
</div>
<div class="loading"></div>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>`;
    $__default['default']( 'body' ).append( dialog );

    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );
    $__default['default']( '#TB_overlay' ).on( 'click', closeDialog );
    let chara_initPrice = getCharaInitPrice();
    const week_ms = 7 * 24 * 3600 * 1000;
    let templeWeek = Math.floor( ( new Date() - new Date( '2019/10/05' ) ) / week_ms + 1 );
    let icoWeek = Math.floor( ( new Date() - new Date( chara_initPrice[ chara.Id ].time ) ) / week_ms + 1 );
    let week = Math.min( templeWeek, icoWeek );
    getData( `chara/auction/list/${chara.Id}/${page}` ).then( ( d ) => {
      $__default['default']( '#TB_window .loading' ).hide();
      if ( d.State == 0 && d.Value.length > 0 ) {
        let success = 0;
        let total = 0;
        d.Value.forEach( ( a ) => {
          let state = "even";
          let name = "失败";
          if ( a.State == 1 ) {
            success++;
            total += a.Amount;
            state = "raise";
            name = "成功";
          }
          let record = `
<div class="row"><span class="time">${formatDate(a.Bid)}</span>
<span class="user"><a target="_blank" href="/user/${a.Username}">${a.Nickname}</a></span>
<span class="price">₵${formatNumber(a.Price, 2)} / ${formatNumber(a.Amount, 0)}</span>
<span class="tag ${state}">${name}</span></div>`;
          $__default['default']( '#TB_window .result' ).append( record );
        } );
        $__default['default']( '#TB_window .desc' ).text( `共有${d.Value.length}人参与拍卖,成功${success}人 / ${total}股` );
        $__default['default']( '#TB_window .result' ).show();
      } else {
        $__default['default']( '#TB_window .desc' ).text( '暂无拍卖数据' );
      }
      $__default['default']( '#TB_window .desc' ).show();
      if ( page > 1 )
        $__default['default']( '#nextweek' ).show();
      if ( page < week )
        $__default['default']( '#lastweek' ).show();
      $__default['default']( '#nextweek' ).on( 'click', () => {
        page--;
        closeDialog();
        openHistoryDialog( chara, page );
      } );
      $__default['default']( '#lastweek' ).on( 'click', () => {
        page++;
        closeDialog();
        openHistoryDialog( chara, page );
      } );
    } );
  }

  function showAuctionHistory( chara ) {
    let button = `<button id="auctionHistorys" class="text_button">[往期拍卖]</button>`;
    $__default['default']( '#auctionHistoryButton' ).after( button );
    $__default['default']( '#auctionHistoryButton' ).hide();
    $__default['default']( '#auctionHistorys' ).on( 'click', () => {
      openHistoryDialog( chara, 1 );
    } );
  }

  function openTradeHistoryDialog( chara ) {
    var dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<div class="title">交易历史记录 - #${chara.Id} 「${chara.Name}」 ₵${formatNumber(chara.Current, 2)} / ${formatNumber(chara.Total, 0)}</div>
<div class="result" style="display:none; max-height: 500px; overflow: auto;"></div>
<div class="desc" style="display:none"></div>
<div class="loading"></div>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>`;
    $__default['default']( 'body' ).append( dialog );

    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );
    $__default['default']( '#TB_overlay' ).on( 'click', closeDialog );
    let tradeHistory, totalPages;
    getData( `chara/charts/${chara.Id}/2019-08-08` ).then( ( d ) => {
      if ( d.State == 0 ) {
        tradeHistory = d.Value.reverse();
        totalPages = Math.ceil( d.Value.length / 50 );
        loadTradeHistory( 1 );
      }
    } );

    function loadTradeHistory( page ) {
      $__default['default']( `#TB_window .loading` ).hide();
      $__default['default']( `#TB_window .result` ).show();
      $__default['default']( `#TB_window .result` ).html( '' );
      let records = tradeHistory.slice( 50 * ( page - 1 ), 50 * page );
      if ( records.length ) {
        for ( let i = 0; i < records.length; i++ ) {
          var record = `<div class="row">
<span class="time" title="交易时间">${formatDate(records[i].Time)}</span>
<span class="price" title="价格">₵${formatNumber((records[i].Price / records[i].Amount), 2)}</span>
<span class="amount" title="数量">${formatNumber(records[i].Amount, 0)}</span>
<span class="price" title="交易额">₵${formatNumber(records[i].Price, 2)}</span>
</div>`;
          $__default['default']( `#TB_window .result` ).append( record );
        }
        $__default['default']( `#TB_window .desc` ).html( '' );
        $__default['default']( `#TB_window .desc` ).text( `共有${tradeHistory.length}条记录,当前 ${page} / ${totalPages} 页` );

        for ( let i = 1; i <= totalPages; i++ ) {
          let pager = `<span class="page" data-page="${i}">[${i}]</span>`;
          $__default['default']( `#TB_window .desc` ).append( pager );
        }

        $__default['default']( `#TB_window .desc .page` ).on( 'click', ( e ) => {
          let page = $__default['default']( e.target ).data( 'page' );
          loadTradeHistory( page );
        } );

        $__default['default']( `#TB_window .result` ).show();
      } else {
        $__default['default']( `#TB_window .desc` ).text( '暂无交易记录' );
      }
      $__default['default']( `#TB_window .desc` ).show();
    }
  }

  function showTradeHistory( chara ) {
    $__default['default']( '#kChartButton' ).after( '<button id="tradeHistoryButton" class="text_button">[交易记录]</button>' );
    $__default['default']( '#tradeHistoryButton' ).on( 'click', () => {
      openTradeHistoryDialog( chara );
    } );
  }

  function sell_out( charaId, init_price ) {
    $__default['default']( $__default['default']( '#grailBox .info .text' )[ 1 ] ).append( `<button id="sell_out" class="text_button" title="以发行价全部卖出">[全部卖出]</button>` );
    $__default['default']( '#sell_out' ).on( 'click', function() {
      getData( `chara/user/${charaId}` ).then( ( d ) => {
        let amount = d.Value.Amount;
        $__default['default']( `.ask .price` ).val( init_price );
        $__default['default']( `.ask .amount` ).val( d.Value.Amount );
      } );
    } );
  }

  function showInitialPrice( charaId ) {
    let chara_initPrice = getCharaInitPrice();
    if ( chara_initPrice[ charaId ] ) {
      let init_price = chara_initPrice[ charaId ].init_price;
      let time = chara_initPrice[ charaId ].time;
      $__default['default']( $__default['default']( '#grailBox .info .text' )[ 1 ] ).append( `<span title="上市时间:${time}">发行价:${init_price}</span>` );
      sell_out( charaId, init_price );
    } else
      getData( `chara/charts/${charaId}/2019-08-08` ).then( ( d ) => {
        let init_price = d.Value[ 0 ].Begin.toFixed( 2 );
        let time = d.Value[ 0 ].Time.replace( 'T', ' ' );
        getCharaInitPrice();
        chara_initPrice[ charaId ] = {
          "init_price": init_price,
          "time": time
        };
        setCharaInitPrice( chara_initPrice );
        $__default['default']( $__default['default']( '#grailBox .info .text' )[ 1 ] ).append( `<span title="上市时间:${time}">发行价:${init_price}</span>` );
        sell_out( charaId, init_price );
      } );
  }

  function showPrice( chara ) {
    let price = chara.Price.toFixed( 2 );
    $__default['default']( $__default['default']( '#grailBox .info .text' )[ 1 ] ).append( `<span>评估价:${price}</span>` );
  }

  function priceWarning() {
    let price = $__default['default']( `.bid .price` ).val();
    let amount = $__default['default']( `.bid .amount` ).val();
    $__default['default']( `#bidButton` ).after( `<button style="display:none" id="confirm_bidButton" class="active bid">买入</button>` );
    $__default['default']( `.bid .price` ).on( 'input', function() {
      let price_now = $__default['default']( `.bid .price` ).val();
      if ( price_now > Math.max( price * 3, 100 ) ) {
        $__default['default']( `.bid .price` ).css( {
          "color": "red"
        } );
        $__default['default']( `#confirm_bidButton` ).show();
        $__default['default']( `#bidButton` ).hide();
      } else {
        $__default['default']( `#confirm_bidButton` ).hide();
        $__default['default']( `#bidButton` ).show();
        $__default['default']( `.bid .price` ).css( {
          "color": "inherit"
        } );
      }
    } );
    $__default['default']( '#confirm_bidButton' ).on( 'click', function() {
      let price = $__default['default']( `.bid .price` ).val();
      let amount = $__default['default']( `.bid .amount` ).val();
      if ( !confirm( `买入价格过高提醒!\n确定以${price}的价格买入${amount}股?` ) ) {
        return;
      }
      $__default['default']( `#bidButton` ).click();
    } );
  }

  function showOwnTemple() {
    let followList = getFollowList();
    let settings = getSettings$1();
    let pre_temple = settings.pre_temple;
    let temples = $__default['default']( '#lastTemples .item' );
    let me = followList.user;
    if ( !me ) {
      me = $__default['default']( '#new_comment .reply_author a' )[ 0 ].href.split( '/' ).pop();
      followList.user = me;
      setFollowList( followList );
    }
    for ( let i = 0; i < temples.length; i++ ) {
      if ( temples[ i ].querySelector( `.name a[href$="${me}"]` ) ) {
        temples[ i ].classList.add( 'my_temple' );
        temples[ i ].classList.remove( 'replicated' );
        if ( pre_temple == 'on' )
          $__default['default']( '#lastTemples' ).prepend( temples[ i ] );
        break;
      }
    }
    $__default['default']( '#expandButton' ).one( 'click', () => {
      showOwnTemple();
    } );
  }

  function showOwnLink() {
    let followList = getFollowList();
    let settings = getSettings();
    let pre_link = settings.pre_temple;
    let links = $__default['default']( '#grailBox .assets_box #lastLinks.assets .link.item' );
    let me = followList.user;
    if ( !me ) {
      me = $__default['default']( '#new_comment .reply_author a' )[ 0 ].href.split( '/' ).pop();
      followList.user = me;
      localStorage.setItem( 'TinyGrail_followList', JSON.stringify( followList ) );
    }
    for ( let i = 0; i < links.length; i++ ) {
      let user = links[ i ].querySelector( '.name a' ).href.split( '/' ).pop();
      if ( user === me ) {
        links[ i ].classList.add( 'my_link' );
        if ( pre_link == 'on' )
          $__default['default']( links[ i ] ).siblings( '.rank.item' ).after( links[ i ] );
        break;
      }
    }
  }

  function showTempleRate( chara ) {
    let b = chara.Type ? 1 : 0;
    let rate = chara.Rate;
    let level = chara.Level;
    let price = chara.Price;
    getData( `chara/temple/${chara.Id}` ).then( ( d ) => {
      let templeAll = {
        1: 0,
        2: 0,
        3: 0
      };
      for ( let i = 0; i < d.Value.length; i++ ) {
        templeAll[ d.Value[ i ].Level ]++;
      }
      let templeRate = rate * ( level + 1 ) * 0.3;
      $__default['default']( '#grailBox .assets_box .bold .sub' ).attr( 'title', '活股股息:' + formatNumber( rate, 2 ) );
      $__default['default']( '#grailBox .assets_box .bold .sub' ).before( `<span class="sub"> (${templeAll[3]} + ${templeAll[2]} + ${templeAll[1]})</span>` );
      $__default['default']( '#expandButton' ).before( `<span class="sub" title="圣殿股息:${formatNumber(templeRate, 2)}"> (${formatNumber(templeRate, 2)})</span>` );
    } );
  }

  function changeTempleCover( charaId ) {
    $__default['default']( '#lastTemples' ).on( 'click', '.card', ( e ) => {
      console.log( `thr: card clicked`, e );
      let followList = getFollowList();
      let me = followList.user;
      let temple = $__default['default']( e.currentTarget ).parent().data( 'temple' );
      let user = temple.Name;
      if ( user == me )
        setChaosCube( temple );
      else
        addButton( temple, user );
    } );

    //   function setChaosCube(temple){
    //     $('#chaosCubeButton').on('click', () => {
    //       let templeId = temple.CharacterId;
    //       ItemsSetting.chaosCube = templeId;
    //       setItemsSetting(ItemsSetting)
    //     });
    //   }
    function addButton( temple, user ) {
      $__default['default']( '#TB_window .action' ).append( `<button id="changeCoverButton2" class="text_button" title="修改圣殿封面">[修改]</button>
<button id="copyCoverButton" class="text_button" title="复制圣殿图片为自己圣殿的封面">[复制]</button>` );

      $__default['default']( '#changeCoverButton2' ).on( 'click', () => {
        let cover = prompt( "图片url(你可以复制已有圣殿图片的url):" );
        let url = 'https://tinygrail.oss-cn-hangzhou.aliyuncs.com/' + cover.match( /cover\/\S+\.jpg/ )[ 0 ];
        postData( `chara/temple/cover/${charaId}/${temple.UserId}`, url ).then( ( d ) => {
          if ( d.State == 0 ) {
            alert( "更换封面成功。" );
            $__default['default']( '#TB_window img.cover' ).attr( 'src', cover );
            $__default['default']( '#grailBox .assets_box .assets .item' ).each( function() {
              if ( user == this.querySelector( '.name a' ).href.split( '/' ).pop() )
                $__default['default']( this ).find( 'div.card' ).css( {
                  "background-image": "url(https://tinygrail.mange.cn/" + cover.match( /cover\/\S+\.jpg/ )[ 0 ] + "!w150)"
                } );
            } );
          } else {
            alert( d.Message );
          }
        } );
      } );

      $__default['default']( '#copyCoverButton' ).on( 'click', () => {
        let cover = $__default['default']( '#TB_window .container .cover' ).attr( 'src' );
        let url = 'https://tinygrail.oss-cn-hangzhou.aliyuncs.com/' + cover.match( /cover\/\S+\.jpg/ )[ 0 ];
        postData( `chara/temple/cover/${charaId}`, url ).then( ( d ) => {
          if ( d.State == 0 ) {
            alert( "更换封面成功。" );
            location.reload();
          } else {
            alert( d.Message );
          }
        } );
      } );
    }
  }

  function mergeorderList( orderListHistory ) {
    let mergedorderList = [],
      i = 0;
    mergedorderList.push( orderListHistory[ 0 ] );
    for ( let j = 1; j < orderListHistory.length; j++ ) {
      if ( ( orderListHistory[ j ].Price == mergedorderList[ i ].Price ) && Math.abs( new Date( orderListHistory[ j ].TradeTime ) - new Date( mergedorderList[ i ].TradeTime ) ) < 10 * 1000 ) {
        //10s内同价格订单合并
        mergedorderList[ i ].Amount += orderListHistory[ j ].Amount;
      } else {
        mergedorderList.push( orderListHistory[ j ] );
        i++;
      }
    }
    return mergedorderList;
  }

  function mergeorderListHistory( charaId ) {
    let settings = getSettings();
    if ( settings.merge_order == 'on' ) {
      getData( `chara/user/${charaId}` ).then( ( d ) => {
        if ( d.State === 0 && d.Value ) {
          $__default['default']( `.ask .ask_list li[class!=ask]` ).hide();
          let askHistory = mergeorderList( d.Value.AskHistory );
          for ( let i = 0; i < askHistory.length; i++ ) {
            let ask = askHistory[ i ];
            if ( ask )
              $__default['default']( '.ask .ask_list' ).prepend( `<li title="${formatDate(ask.TradeTime)}">₵${formatNumber(ask.Price, 2)} / ${formatNumber(ask.Amount, 0)} / +${formatNumber(ask.Amount * ask.Price, 2)}<span class="cancel">[成交]</span></li>` );
          }
          $__default['default']( `.bid .bid_list li[class!=bid]` ).hide();
          let bidHistory = mergeorderList( d.Value.BidHistory );
          for ( let i = 0; i < bidHistory.length; i++ ) {
            let bid = bidHistory[ i ];
            if ( bid )
              $__default['default']( '.bid .bid_list' ).prepend( `<li title="${formatDate(bid.TradeTime)}">₵${formatNumber(bid.Price, 2)} / ${formatNumber(bid.Amount, 0)} / -${formatNumber(bid.Amount * bid.Price, 2)}<span class="cancel">[成交]</span></li>` );
          }

        }
      } );
    }
  }

  function openBuildDialog( chara ) {
    let autoTempleList = getAutoTempleList$1();
    let charaId = chara.Id;
    if ( chara.CharacterId )
      charaId = chara.CharacterId;
    let target = 500,
      bidPrice = 10;
    let intempleList = false,
      index = 0;
    for ( let i = 0; i < autoTempleList.length; i++ ) {
      if ( autoTempleList[ i ].charaId == charaId ) {
        target = autoTempleList[ i ].target;
        bidPrice = autoTempleList[ i ].bidPrice;
        intempleList = true;
        index = i;
      }
    }
    let dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<div class="title" title="目标数量 / 买入价格">
自动建塔 - #${charaId} 「${chara.Name}」 ${target} / ₵${bidPrice}</div>
<div class="desc"><p>当已献祭股数+持有股数达到目标数量时将自动建塔</p>
输入 目标数量 / 买入价格(不超过此价格的卖单将自动买入)</div>
<div class="label"><div class="trade build">
<input class="target" type="number" style="width:150px" title="目标数量" value="${target}">
<input class="bidPrice" type="number" style="width:100px" title="卖出下限" value="${bidPrice}">
<button id="startBuildButton" class="active">自动建塔</button><button id="cancelBuildButton">取消建塔</button></div>
<div class="loading" style="display:none"></div>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>`;
    $__default['default']( 'body' ).append( dialog );

    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );

    $__default['default']( '#cancelBuildButton' ).on( 'click', function() {
      if ( intempleList ) {
        autoTempleList.splice( index, 1 );
        setAutoTempleList( autoTempleList );
        alert( `取消自动建塔${chara.Name}` );
        $__default['default']( '#autobuildButton' ).text( '[自动建塔]' );
      }
      closeDialog();
    } );

    $__default['default']( '#startBuildButton' ).on( 'click', function() {
      let info = {};
      info.charaId = charaId.toString();
      info.name = chara.Name;
      info.target = $__default['default']( '.trade.build .target' ).val();
      info.bidPrice = $__default['default']( '.trade.build .bidPrice' ).val();
      if ( intempleList ) {
        autoTempleList.splice( index, 1 );
        autoTempleList.unshift( info );
      } else
        autoTempleList.unshift( info );
      setAutoTempleList( autoTempleList );
      alert( `启动自动建塔#${info.charaId} ${info.name}` );
      closeDialog();
      $__default['default']( '#autobuildButton' ).text( '[自动建塔中]' );
      autoBuildTemple( [ info ] );
    } );
  }

  function setBuildTemple( chara ) {
    let in_TempleList = false;
    let charaId = chara.Id;
    let autoTempleList = getAutoTempleList$1();
    if ( chara.CharacterId )
      charaId = chara.CharacterId;
    for ( let i = 0; i < autoTempleList.length; i++ ) {
      if ( autoTempleList[ i ].charaId == charaId )
        in_TempleList = true;
    }
    setAutoTempleList( autoTempleList );
    let button;
    if ( in_TempleList ) {
      button = `<button id="autobuildButton" class="text_button">[自动建塔中]</button>`;
    } else {
      button = `<button id="autobuildButton" class="text_button">[自动建塔]</button>`;
    }
    if ( $__default['default']( '#buildButton' ).length )
      $__default['default']( '#buildButton' ).after( button );
    else
      $__default['default']( '#grailBox .title .text' ).after( button );

    $__default['default']( '#autobuildButton' ).on( 'click', () => {
      openBuildDialog( chara );
    } );
  }

  function followChara( charaId ) {
    let followList = getFollowList();
    let button = `<button id="followCharaButton" class="text_button">[关注角色]</button>`;
    if ( followList.charas.includes( charaId ) ) {
      button = `<button id="followCharaButton" class="text_button">[取消关注]</button>`;
    }
    if ( $__default['default']( '#kChartButton' ).length )
      $__default['default']( '#kChartButton' ).before( button );
    else
      $__default['default']( '#grailBox .title .text' ).after( button );

    $__default['default']( '#followCharaButton' ).on( 'click', () => {
      if ( followList.charas.includes( charaId ) ) {
        followList.charas.splice( followList.charas.indexOf( charaId ), 1 );
        $__default['default']( '#followCharaButton' ).text( '[关注角色]' );
      } else {
        followList.charas.unshift( charaId );
        $__default['default']( '#followCharaButton' ).text( '[取消关注]' );
      }
      setFollowList( followList );
    } );
  }

  function followAuctions( charaId ) {
    getData( `chara/user/${charaId}/tinygrail/false` ).then( ( d ) => {
      let followList = getFollowList();
      if ( d.State == 0 ) {
        let button;
        if ( followList.auctions.includes( charaId ) ) {
          button = `<button id="followAuctionButton" class="text_button">[取消关注]</button>`;
        } else {
          button = `<button id="followAuctionButton" class="text_button">[关注竞拍]</button>`;
        }
        $__default['default']( '#buildButton' ).before( button );
        $__default['default']( '#followAuctionButton' ).on( 'click', () => {
          if ( followList.auctions.includes( charaId ) ) {
            followList.auctions.splice( followList.auctions.indexOf( charaId ), 1 );
            $__default['default']( '#followAuctionButton' ).text( '[关注竞拍]' );
          } else {
            followList.auctions.unshift( charaId );
            $__default['default']( '#followAuctionButton' ).text( '[取消关注]' );
          }
          setFollowList( followList );
        } );
      }
    } );
  }

  function add_chara_info() {
    let charaId = $__default['default']( '#grailBox .title .name a' )[ 0 ].href.split( '/' ).pop();
    followChara( charaId ); //关注角色
    followAuctions( charaId ); //关注竞拍情况
    showInitialPrice( charaId ); //显示发行价
    priceWarning(); //买入价格过高提醒
    mergeorderListHistory( charaId ); //合并同一时间订单历史记录
    launchObserver( {
      parentNode: document.body,
      selector: '#lastTemples .item',
      successCallback: () => {
        showOwnTemple(); //显示自己的圣殿
        changeTempleCover( charaId ); //修改他人圣殿封面
      },
    } );
    launchObserver( {
      parentNode: document.body,
      selector: '#lastLinks .link.item',
      successCallback: () => {
        showOwnLink(); //前置自己的连接
      },
    } );
    showGallery(); //查看画廊
    getData( `chara/${charaId}` ).then( ( d ) => {
      let chara = d.Value;
      showAuctionHistory( chara ); //历史拍卖
      showTradeHistory( chara ); //交易记录
      showPrice( chara ); //显示评估价
      showTempleRate( chara ); //显示各级圣殿数量及股息计算值
      setBuildTemple( chara ); //自动建塔
      fixAuctions( chara ); //修改默认拍卖底价和数量
    } );
  }

  function openICODialog( chara ) {
    let fillicoList = getFillICOList();
    let target = 1;
    let inorder = false,
      index = 0;
    for ( let i = 0; i < fillicoList.length; i++ ) {
      if ( fillicoList[ i ].Id == chara.Id ) {
        target = fillicoList[ i ].target;
        inorder = true;
        index = i;
      }
    }
    let dialog = `<div id="TB_overlay" class="TB_overlayBG TB_overlayActive"></div>
<div id="TB_window" class="dialog" style="display:block;max-width:640px;min-width:400px;">
<div class="title">自动补款 - #${chara.CharacterId} 「${chara.Name}」 lv${target}</div>
<div class="desc">目标等级:<input type="number" class="target" min="1" max="10" step="1" value="${target}" style="width:50px"></div>
<div class="label"><div class="trade ico">
<button id="startfillICOButton" class="active">自动补款</button>
<button id="fillICOButton" style="background-color: #5fda15;">立即补款</button>
<button id="cancelfillICOButton">取消补款</button></div>
<div class="loading" style="display:none"></div>
<a id="TB_closeWindowButton" title="Close">X关闭</a>
</div>`;
    $__default['default']( 'body' ).append( dialog );

    $__default['default']( '#TB_closeWindowButton' ).on( 'click', closeDialog );

    $__default['default']( '#cancelfillICOButton' ).on( 'click', function() {
      if ( inorder ) {
        alert( `取消自动补款${chara.Name}` );
        $__default['default']( '#followICOButton' ).text( '[自动补款]' );
        fillicoList.splice( index, 1 );
        setFillICOList( fillicoList );
      }
      closeDialog();
      console.log( fillicoList );
    } );

    $__default['default']( '#startfillICOButton' ).on( 'click', function() {
      let target = parseFloat( $__default['default']( '.desc .target' ).val() );
      if ( target <= 0 || !Number.isInteger( target ) ) {
        alert( '请输入正整数!' );
        return;
      }
      let info = {};
      info.Id = chara.Id.toString();
      info.charaId = chara.CharacterId.toString();
      info.name = chara.Name;
      info.target = target;
      info.end = chara.End;
      if ( inorder ) {
        fillicoList[ index ] = info;
      } else
        fillicoList.push( info );
      setFillICOList( fillicoList );
      alert( `启动自动补款#${chara.Id} ${chara.Name}` );
      $__default['default']( '#followICOButton' ).text( '[自动补款中]' );
      closeDialog();
      console.log( fillicoList );
    } );

    $__default['default']( '#fillICOButton' ).on( 'click', function() {
      let target = parseFloat( $__default['default']( '.desc .target' ).val() );
      if ( target <= 0 || !Number.isInteger( target ) ) {
        alert( '请输入正整数!' );
        return;
      }
      let info = {};
      info.Id = chara.Id.toString();
      info.charaId = chara.CharacterId.toString();
      info.name = chara.Name;
      info.target = target;
      info.end = chara.End;
      closeDialog();
      if ( confirm( `立即补款#${chara.Id} ${chara.Name} 至 lv${target}` ) ) {
        fullfillICO( [ info ] );
      }
    } );
  }

  function setFullFillICO( chara ) {
    let fillicoList = getFillICOList();
    let button, inorder = false;
    let charaId = chara.CharacterId;
    for ( let i = 0; i < fillicoList.length; i++ ) {
      if ( fillicoList[ i ].charaId == charaId ) {
        inorder = true;
      }
    }
    if ( inorder ) {
      button = `<button id="followICOButton" class="text_button">[自动补款中]</button>`;
    } else {
      button = `<button id="followICOButton" class="text_button">[自动补款]</button>`;
    }
    $__default['default']( '#grailBox .title .text' ).after( button );
    $__default['default']( '#followICOButton' ).on( 'click', () => {
      openICODialog( chara );
    } );
  }

  function showEndTime( chara ) {
    let endTime = ( chara.End ).slice( 0, 19 );
    $__default['default']( '#grailBox .title .text' ).append( `<div class="sub" style="margin-left: 20px">结束时间: ${endTime}</div>` );
  }

  function add_ico_info() {
    let charaId = location.pathname.split( '/' ).pop();
    followChara( charaId ); //关注角色
    getData( `chara/${charaId}` ).then( ( d ) => {
      let chara = d.Value;
      showEndTime( chara ); //显示结束时间
      setBuildTemple( chara ); //自动建塔
      setFullFillICO( chara ); //自动补款
    } );
  }

  //=======================================================================================================//

  setInterval( autoFillTemple, 60 * 60 * 1000 );
  setInterval( autoTemple, 60 * 60 * 1000 );
  setInterval( fillICO, 30 * 1000 );

  // character page
  if ( location.pathname.startsWith( '/rakuen/topic/crt' ) || location.pathname.startsWith( '/character' ) ) {
    let parentNode = document.getElementById( 'subject_info' ) || document.getElementById( 'columnCrtB' );
    // charater trade info
    let chara_fetched = false;
    launchObserver( {
      parentNode: parentNode,
      selector: '#grailBox .assets_box',
      failCallback: () => {
        chara_fetched = false;
      },
      successCallback: () => {
        if ( chara_fetched ) return;
        chara_fetched = true;
        add_chara_info();
      },
      stopWhenSuccess: false,
    } );
    // charater ico info
    let ico_fetched = false;
    launchObserver( {
      parentNode: parentNode,
      selector: '#grailBox .trade .money',
      failCallback: () => {
        ico_fetched = false;
      },
      successCallback: () => {
        if ( ico_fetched ) return;
        ico_fetched = true;
        add_ico_info();
      },
      stopWhenSuccess: false,
    } );
  }
  // rakuen homepage
  else if ( location.pathname.startsWith( '/rakuen/home' ) ) {
    //周六未领取股息则自动领取
    if ( settings.get_bonus == 'on' ) getShareBonus();
    launchObserver( {
      parentNode: document.body,
      selector: '#topWeek',
      successCallback: () => {
        hideBonusButton(); //隐藏签到
        showTopWeek(); //显示萌王榜排名数值
        showGallery(); //显示画廊
      },
    } );
    let chara_fetched = false;
    launchObserver( {
      parentNode: document.body,
      selector: '#grailBox .assets_box',
      failCallback: () => {
        chara_fetched = false;
      },
      successCallback: () => {
        if ( chara_fetched ) return;
        chara_fetched = true;
        add_chara_info();
      },
      stopWhenSuccess: false,
    } );
  }
  // menu page
  else if ( location.pathname.startsWith( '/rakuen/topiclist' ) ) {
    setTimeout( function() {
      loadHelperMenu();
    }, 500 );
  }
  // user homepage
  else if ( location.pathname.startsWith( '/user' ) ) {
    launchObserver( {
      parentNode: document.body,
      selector: '#grail',
      successCallback: () => {
        showHideGrailBox();
        showGallery();
      },
    } );
    let chara_fetched = false;
    launchObserver( {
      parentNode: document.body,
      selector: '#grailBox .assets_box',
      failCallback: () => {
        chara_fetched = false;
      },
      successCallback: () => {
        if ( chara_fetched ) return;
        chara_fetched = true;
        add_chara_info();
      },
      stopWhenSuccess: false,
    } );
  }

}($));