import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener} from '@angular/core';

import {
  getPosDistance,
  Label, Line, moveItem,
  MySprite, randomSortByArr, removeItemFromArr, rotateItem, RoundSprite, ShapeRect, ShapeRectNew, showItem, tweenChange,

} from './Unit';
import {res, resAudio} from './resources';

import {Subject} from 'rxjs';
import {debounceTime} from 'rxjs/operators';

import TWEEN from '@tweenjs/tween.js';
import {HttpClient} from '@angular/common/http';
import {RankStatisticsManager} from './RankStatistics';




@Component({
  selector: 'app-play',
  templateUrl: './play.component.html',
  styleUrls: ['./play.component.css']
})
export class PlayComponent implements OnInit, OnDestroy {

  @ViewChild('canvas', {static: true }) canvas: ElementRef;
  @ViewChild('wrap', {static: true }) wrap: ElementRef;

  // 数据
  data;

  ctx;

  canvasWidth = 1280; // canvas实际宽度
  canvasHeight = 720; // canvas实际高度

  canvasBaseW = 1280; // canvas 资源预设宽度
  canvasBaseH = 720;  // canvas 资源预设高度

  mx; // 点击x坐标
  my; // 点击y坐标


  // 资源
  rawImages = new Map(res);
  rawAudios = new Map(resAudio);

  images = new Map();

  animationId: any;
  winResizeEventStream = new Subject();

  audioObj = {};

  renderArr;
  mapScale = 1;

  canvasLeft;
  canvasTop;

  saveKey = 'hw_online_005';



  canTouch = true;


  brushArr;
  curBrush;
  artboard;
  artboardSmall;

  brushPointArr;
  brushDownFlag;
  lineArr;
  curLine;

  offCanvas;

  cleanBtn;
  clockBar;

  wordArr;
  curWordIndex;

  curDrawTime;
  totalDrawTime;
  lastTime;
  clockStartFlag;

  guessFlag = false;
  guessPageArr;
  roleArr;
  roleIndex;
  curRole;
  clockBg;
  maskLayer;

  cleanId;
  guessWordArr;
  guessWordOffX;
  guessWordOffY;
  guessLabel;
  guessCancleBtn;
  guessOkBtn;
  guessWordBg;
  roleBg;
  drawWordLabel;
  drawWordBg;

  coverPageArr;
  startBtn;

  teachFlag = false;

  lastSendTime;


  uuid = 0;
  user = {};

  serverRoleArr;
  serverAllUser;

  startFlag = false;
  needSendDataFlag = false;

  sendServerDisTime = 200;
  drawSenderId;

  guessLineArr;
  gameEndFlag;

  endPageArr;
  showPetalFlag;
  petalTime;

  roleData;
  rightIconObj;


  teacherPage;
  teacherPageArr;
  scoreDataArr;
  teacherPageListArr;
  curTeacherPage = 1;
  totalTeacherPage = 1;
  teacherPageLabel;
  arrowL;
  arrowR;

  gameResultArr = [];

  drawIcon;

  MESSAGE_START = 'hw-gameStart';
  statisticsManager = new RankStatisticsManager();
  startDate;
  wrongArr;
  totalDuration;

  curWrongRoleArr


  @HostListener('window:resize', ['$event'])
  onResize(event) {
    this.winResizeEventStream.next();
  }

  constructor(private http: HttpClient) {}

  ngOnInit() {

    this.data = {};

    // 获取数据
    const getData = (<any> window).courseware.getData;
    getData((data, aspect) => {



      if (aspect) {
        console.log('aspect : ', aspect);
        this.serverAllUser = aspect.all_user;
      }
      console.log('air : ', window['air']);
      console.log('air _ airClassInfo: ', window['air'].airClassInfo);
      console.log('air _ airClassInfo _ user: ', window['air'].airClassInfo.user);

      if (window['air'].airClassInfo.user.classRole == 'tea') {
        this.teachFlag = true;
      }
      this.uuid = window['air'].airClassInfo.user.uuid;
      this.user = window['air'].airClassInfo.user;


      if (data && typeof data == 'object') {
        this.data = data;
      }
      console.log('data:' , data);

      // 初始化 各事件监听
      this.initListener();

      // 若无数据 则为预览模式 需要填充一些默认数据用来显示
      this.initDefaultData();

      // 初始化 音频资源
      this.initAudio();
      // 初始化 图片资源
      this.initImg();
      // 开始预加载资源
      this.load();

    }, this.saveKey);

  }

  ngOnDestroy() {
    window['curCtx'] = null;
    window.cancelAnimationFrame(this.animationId);

    if (this.cleanId) {
      clearInterval(this.cleanId);
    }

    this.removeServerSender();
  }


  load() {

    // window["air"].hideAirClassLoading(this.saveKey, this.data);

    // console.log('in load 1');
    this.loadResources().then(() => {
      // console.log('in load 2');

      this.init();
      // console.log('in load 3');

      this.update();
      // console.log('in load 4');


      this.addServerListener();
      // console.log('in load 5');

      window["air"].hideAirClassLoading(this.saveKey, this.data);

      // console.log('in load 6');


    });
  }


  init() {

    this.initCtx();
    this.initData();
    this.initView();
  }

  initCtx() {
    this.canvasWidth = this.wrap.nativeElement.clientWidth;
    this.canvasHeight = this.wrap.nativeElement.clientHeight;
    this.canvas.nativeElement.width = this.wrap.nativeElement.clientWidth;
    this.canvas.nativeElement.height = this.wrap.nativeElement.clientHeight;


    this.ctx = this.canvas.nativeElement.getContext('2d');
    this.canvas.nativeElement.width = this.canvasWidth;
    this.canvas.nativeElement.height = this.canvasHeight;

    // window['curCtx'] = this.ctx;
    // window['curCanvas'] = this.canvas;


    // const canvas = new OffscreenCanvas(this.canvasWidth, this.canvasHeight);
    const canvas = document.createElement('canvas');
    canvas.width = this.wrap.nativeElement.clientWidth;
    canvas.height = this.wrap.nativeElement.clientHeight;

    const ctx = canvas.getContext('2d');
    this.offCanvas = canvas;

    window['curCtx'] = ctx;
    window['curCanvas'] = this.canvas;

  }





  addServerListener() {

    const c = (<any> window).courseware;


    c.onEvent('userchange', (data, next) => {
      //data的结构如下
      /*{
       *  id: '变动用户的ID',
       *  connected: true/false,  true: 连接的，false:d断开的
       *  status: 'connect/reconnect',  connect：新建连接，reconnect:重新连接；这个字段在断开连接的事件里是缺失的
       *  all_user: []  这个是现有的用户列表
       *}
       */
      console.log('userchange, data: ', data);
      //处理事件的同步逻辑

      //在逻辑处理完之后一定要执行next方法,用于解锁事件队列



      // if (this.teachFlag) {
        this.syncAllUser(data.all_user);
        this.initCurRole();

      // }

      next();
    });



    c.onEvent(this.MESSAGE_START, (data, next) => {
      console.log('data: ', data);


      if (this.startFlag) {
        next();
        return;
      }


      // const roleData = this.roleData;
      // const roleIndex = this.roleIndex;
      // const wordArr = this.wordArr;
      // const date = new Date().getTime();
      const {roleData, roleIndex, wordArr} = data;


      this.coverPageArr.length = 0;
      this.startFlag = true;
      this.gameResultArr = [];

      this.roleData = roleData;
      this.roleIndex = roleIndex;
      this.wordArr = wordArr;
      this.scoreDataArr = [];
      this.gameResultArr.push(this.scoreDataArr);

      this.rightIconObj = {};

      this.curWordIndex = this.roleIndex;

      this.startDate = new Date();
      this.wrongArr.push(this.roleIndex + 1);
      this.initCurWrongRoleArr();


      this.initRole(roleData);

      this.initCurRole();
      this.initCurView();

      this.onServerRoundStart();


      if (this.teachFlag) {
        this.teacherPage.visible = true;
      }

      this.canTouch = true;

      next();
    });

    c.onEvent('newRound', (data, next) => {
      console.log('newRound data: ', data);

      // const roleData = this.roleData;
      // const roleIndex = this.roleIndex;
      // const wordArr = this.wordArr;
      // const date = new Date().getTime();





      const {roleData, roleIndex, wordArr, gameResultArr} = data;

      this.roleData = roleData;
      this.roleIndex = roleIndex;
      this.wordArr = wordArr;
      this.scoreDataArr = [];

      if (this.teachFlag) {
        this.gameResultArr.push(this.scoreDataArr);
      } else {
        this.gameResultArr = gameResultArr;
      }

      this.rightIconObj = {};

      this.curWordIndex = this.roleIndex;

      this.startDate = new Date();
      this.wrongArr.push(this.roleIndex + 1);



      this.initCurWrongRoleArr();


      if (!this.teachFlag) {
        this.timeEnd();
      }
      this.startNewRound();

      next();
    });


    c.onEvent('drawChange', (data, next) => {
      console.log('data: ', data);

      this.drawSmallArtboard(data);

      next();
    });



    c.onEvent('answerRight', (data, next) => {
      console.log('data: ', data);

      this.setRoleRight(data.user);

      this.rightIconObj[data.user.uuid] = true;

      if (this.teachFlag) {
        this.addTeacherPageData(data);

        this.deleteOnWrongRoleArr(data.user.uuid);
        this.addStuRightRankData(data);
        this.statisticsManager.sendRankDataEvent();
      }

      next();
    });




    this.addScreenshotListener();

  }

  sendServerEvent(key, data) {

    // console.log('send event key: ', key);
    // console.log('send event data: ', data);
    const c = (<any> window).courseware;
    c.sendEvent(key, data);
  }

  addScreenshotListener() {

    // 添加截图监听
    const c = (<any> window).courseware;
    const uploadUrl = c.uploadUrl();
    c.onEvent('screenshot', (data, next) => {

      // canvas转图片
      const src = this.canvas.nativeElement.toDataURL("image/png");
      const arr = src.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while ( n -- ) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      const obj = new Blob([u8arr], {type: mime});
      const fd = new FormData();
      fd.append("file", obj, "cw_cover.png");

      // 上传截图
      this.http.post(uploadUrl, fd).subscribe((res) => {
        // 存储服务器的截图url
        if (res['url']) {
          c.sendEvent('screenshot', {url: res['url']});
        }
      });

      next();
    });
  }

  syncAllUser(allUserData) {


    console.log(' syncAllUser 1 ');
    if (!this.serverRoleArr) {
      this.serverRoleArr = [];
    }

    console.log(' syncAllUser 2 ');

    for (let i = 0; i < allUserData.length; i++) {

      const {user, connected} = allUserData[i];

      let needAddFlag = true;
      for (let j = 0; j < this.serverRoleArr.length; j++) {
        if (this.serverRoleArr[j].uuid == user.uuid) { //  已经存在
          this.serverRoleArr[j].connected = connected;
          needAddFlag = false;
          break;
        }
      }
      if (needAddFlag) { // 不存在 新添加
        user['connected'] = connected;
        this.serverRoleArr.push(user);
      }

    }

    console.log(' syncAllUser 3 ', this.serverRoleArr);

    // if (this.roleArr && this.roleArr.length > 0) {
    this.initRole(this.serverRoleArr);
    // }
  }



  initCurWrongRoleArr() {
    if (!this.teachFlag) {
      return;
    }

    console.log('this.roleData - 1:' , this.roleData)
    this.curWrongRoleArr = this.roleData.concat();
    this.curWrongRoleArr.splice(this.roleIndex, 1);
    console.log('this.roleData - 2:' , this.roleData)
  }

  deleteOnWrongRoleArr(uuid) {
    for (let i = 0; i < this.curWrongRoleArr.length; i++) {
      if (this.curWrongRoleArr[i].uuid == uuid) {
        this.curWrongRoleArr.splice(i, 1);
        return;
      }
    }
  }




  updateItem(item) {
    if (item) {
      item.update();
    }
  }

  updateArr(arr) {
    if (!arr) {
      return;
    }
    for (let i = 0; i < arr.length; i++) {
      arr[i].update(this);
    }
  }







  initListener() {

    this.winResizeEventStream
      .pipe(debounceTime(500))
      .subscribe(data => {
        this.renderAfterResize();
      });


    // ---------------------------------------------
    const setParentOffset = () => {
      const rect = this.canvas.nativeElement.getBoundingClientRect();
      this.canvasLeft = rect.left;
      this.canvasTop = rect.top;
    };
    const setMxMyByTouch = (event) => {
      if (event.touches.length <= 0) {
        return;
      }
      if (this.canvasLeft == null) {
        setParentOffset();
      }
      this.mx = event.touches[0].pageX - this.canvasLeft;
      this.my = event.touches[0].pageY - this.canvasTop;
    };

    const setMxMyByMouse = (event) => {
      this.mx = event.offsetX;
      this.my = event.offsetY;
    };
    // ---------------------------------------------


    let firstTouch = true;

    const touchDownFunc = (e) => {
      if (firstTouch) {
        firstTouch = false;
        removeMouseListener();
      }
      setMxMyByTouch(e);
      this.mapDown(e);
    };
    const touchMoveFunc = (e) => {
      setMxMyByTouch(e);
      this.mapMove(e);
    };
    const touchUpFunc = (e) => {
      setMxMyByTouch(e);
      this.mapUp(e);
    };

    const mouseDownFunc = (e) => {
      if (firstTouch) {
        firstTouch = false;
        removeTouchListener();
      }
      setMxMyByMouse(e);
      this.mapDown(e);
    };
    const mouseMoveFunc = (e) => {
      setMxMyByMouse(e);
      this.mapMove(e);
    };
    const mouseUpFunc = (e) => {
      setMxMyByMouse(e);
      this.mapUp(e);
    };


    const element = this.canvas.nativeElement;

    const addTouchListener = () => {
      element.addEventListener('touchstart', touchDownFunc);
      element.addEventListener('touchmove', touchMoveFunc);
      element.addEventListener('touchend', touchUpFunc);
      element.addEventListener('touchcancel', touchUpFunc);
    };
    const removeTouchListener = () => {
      element.removeEventListener('touchstart', touchDownFunc);
      element.removeEventListener('touchmove', touchMoveFunc);
      element.removeEventListener('touchend', touchUpFunc);
      element.removeEventListener('touchcancel', touchUpFunc);
    };

    const addMouseListener = () => {
      element.addEventListener('mousedown', mouseDownFunc);
      element.addEventListener('mousemove', mouseMoveFunc);
      element.addEventListener('mouseup', mouseUpFunc);
    };
    const removeMouseListener = () => {
      element.removeEventListener('mousedown', mouseDownFunc);
      element.removeEventListener('mousemove', mouseMoveFunc);
      element.removeEventListener('mouseup', mouseUpFunc);
    };

    addMouseListener();
    addTouchListener();
  }


  playAudio(key, now = false, callback = null) {

    const audio = this.audioObj[key];

    try {
      if (audio) {
        if (now) {
          audio.pause();
          audio.currentTime = 0;
        }

        if (callback) {
          audio.onended = () => {
            callback();
          };
        }
        audio.play();
      }
    } catch (e) {
      console.log('e: ', e);
    }

  }



  loadResources() {
    const pr = [];
    this.rawImages.forEach((value, key) => {// 预加载图片

      const p = this.preload(value)
        .then(img => {
          this.images.set(key, img);
        })
        .catch(err => console.log(err));

      pr.push(p);
    });

    this.rawAudios.forEach((value, key) => {// 预加载音频

      const a = this.preloadAudio(value)
        .then(() => {
          // this.images.set(key, img);
        })
        .catch(err => console.log(err));

      pr.push(a);
    });
    return Promise.all(pr);
  }

  preload(url) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      // img.crossOrigin = "anonymous";
      img.onload = () => resolve(img);
      img.onerror = reject;
      img.src = url;
    });
  }

  preloadAudio(url) {
    return new Promise((resolve, reject) => {
      const audio = new Audio();
      // audio.addEventListener('loadedmetadata', () => {
      //   resolve();
      // });
      // audio.oncanplay = (a) => {
      //   resolve();
      // };
      audio.onerror = () => {
        reject();
      };
      audio.src = url;
      audio.load();

      resolve();


    });
  }


  renderAfterResize() {
    this.canvasWidth = this.wrap.nativeElement.clientWidth;
    this.canvasHeight = this.wrap.nativeElement.clientHeight;
    this.init();
  }





  checkClickTarget(target) {

    const rect = target.getBoundingBox();

    if (this.checkPointInRect(this.mx, this.my, rect)) {
      return true;
    }
    return false;
  }

  getWorlRect(target) {

    let rect = target.getBoundingBox();

    if (target.parent) {

      const pRect = this.getWorlRect(target.parent);
      rect.x += pRect.x;
      rect.y += pRect.y;
    }
    return rect;
  }

  checkPointInRect(x, y, rect) {
    if (x >= rect.x && x <= rect.x + rect.width) {
      if (y >= rect.y && y <= rect.y + rect.height) {
        return true;
      }
    }
    return false;
  }





  addUrlToAudioObj(key, url = null, vlomue = 1, loop = false, callback = null) {

    const audioObj = this.audioObj;

    if (url == null) {
      url = key;
    }

    this.rawAudios.set(key, url);

    const audio = new Audio();
    audio.src = url;
    audio.load();
    audio.loop = loop;
    audio.volume = vlomue;

    audioObj[key] = audio;

    if (callback) {
      audio.onended = () => {
        callback();
      };
    }
  }

  addUrlToImages(url) {
    this.rawImages.set(url, url);
  }






  // ======================================================编写区域==========================================================================





  /**
   * 添加默认数据 便于无数据时的展示
   */
  initDefaultData() {

    if (!this.data.pic_url) {
      this.data.pic_url = 'assets/play/default/pic.jpg';
      this.data.pic_url_2 = 'assets/play/default/pic.jpg';
    }

    if (!this.data.wordArr) {
      this.data.wordArr = [
        {
          word: 'apple',
          time: 30
        },
        {
          word: 'orange',
          time: 30
        }
      ];
    }

  }


  /**
   * 添加预加载图片
   */
  initImg() {

    this.addUrlToImages(this.data.pic_url);
    this.addUrlToImages(this.data.pic_url_2);

  }

  /**
   * 添加预加载音频
   */
  initAudio() {

    // // 音频资源
    // this.addUrlToAudioObj(this.data.audio_url);
    //
    // 音效
    this.addUrlToAudioObj('brush_change', this.rawAudios.get('brush_change'), 0.5);
    this.addUrlToAudioObj('clean', this.rawAudios.get('clean'));
    this.addUrlToAudioObj('countdown', this.rawAudios.get('countdown'));
    this.addUrlToAudioObj('finish', this.rawAudios.get('finish'));
    this.addUrlToAudioObj('right', this.rawAudios.get('right'));
    this.addUrlToAudioObj('wrong', this.rawAudios.get('wrong'));
    this.addUrlToAudioObj('tip', this.rawAudios.get('tip'));

  }



  /**
   * 初始化数据
   */
  initData() {

    const sx = this.canvasWidth / this.canvasBaseW;
    const sy = this.canvasHeight / this.canvasBaseH;
    const s = Math.min(sx, sy);
    this.mapScale = s;

    // this.mapScale = sx;
    // this.mapScale = sy;

    this.wrongArr = [];
    this.totalDuration = 0;


    this.renderArr = [];

    this.brushDownFlag = false;

    this.lineArr = [];

    this.wordArr = randomSortByArr( this.data.wordArr );
    this.curWordIndex = 0;

    this.clockStartFlag = false;
    this.guessFlag = false;

    this.roleIndex = 0;
    this.lastSendTime = 0;

    this.gameEndFlag = false;
    this.endPageArr = [];


  }



  /**
   * 初始化试图
   */
  initView() {



    // this.teachFlag = true;

    this.initBg();

    // this.initRole();
    this.initServerRole();

    this.initGuessView();


    // this.countdownGuessStart();
    // this.countdownDrawStart();
    //
    this.initMask();

    // this.initCurRole();
    // this.initCurView();

    // this.onServerRoundStart();


    this.initCoverPage();
    // this.test();

    this.initTeacherPage();



    this.syncPage();

  }

  syncPage() {
    if (!this.serverAllUser) {
      return;
    }

    let teacherData;
    for (let i = 0; i < this.serverAllUser.length; i++) {
      const {user} = this.serverAllUser[i];
      if (user.classRole == 'tea') {
        teacherData = this.serverAllUser[i];
        break;
      }
    }

    if (!teacherData || !teacherData.aspect) {
      return;
    }


    console.log('type: ',  typeof teacherData.aspect)

    teacherData.aspect = JSON.parse(teacherData.aspect);
    const {roleData, roleIndex, wordArr, gameResultArr} = teacherData.aspect;

    console.log('teacherData.aspect: ', teacherData.aspect);

    this.initRole(roleData);

    this.coverPageArr.length = 0;
    this.startFlag = true;

    this.roleData = roleData;
    this.roleIndex = roleIndex;
    this.wordArr = wordArr;
    this.scoreDataArr = [];
    this.gameResultArr = gameResultArr;
    this.gameResultArr.push(this.scoreDataArr);

    this.rightIconObj = {};

    this.curWordIndex = this.roleIndex;


    this.startDate = new Date();
    this.wrongArr.push(this.roleIndex + 1);
    this.initCurWrongRoleArr();

    const { rankData } = teacherData.aspect;
    this.sendServerEvent(this.MESSAGE_START, {startData: {quesNum: this.roleArr.length}, roleData, roleIndex, wordArr, gameResultArr, rankData, start: true});



    console.log('check Game end 1, index: ', this.roleIndex);
    console.log('check Game end 1, length: ', this.roleArr.length);
    if (this.roleIndex >= this.roleArr.length) {
      console.log('game end');
      this.gameEnd();

    } else {
      this.initCurRole();
      this.initCurView();

      this.onServerRoundStart();
    }



    if (this.teachFlag) {
      this.teacherPage.visible = true;
    }

  }


  initTeacherPage() {


    this.teacherPageArr = [];
    this.scoreDataArr = [];
    this.teacherPageListArr = [];

    // const bg = new MySprite();
    const bg = new ShapeRect();
    bg.setSize(this.canvasWidth, this.canvasHeight);
    bg.fillColor = '#000000';
    bg.alpha = 0.2;

    // bg.init(this.images.get('bg'));
    // bg.x = this.canvasWidth / 2;
    // bg.y = this.canvasHeight / 2;
    // const sx = this.canvasWidth / bg.width;
    // const sy = this.canvasHeight / bg.height;
    // const s = Math.max(sx, sy);
    // bg.setScaleXY(s);
    bg.visible = false;
    this.teacherPage = bg;
    this.teacherPageArr.push(bg);


    const w = 600;
    const h = 500;
    const lineW = 4 * this.mapScale;
    const frame = new ShapeRectNew();
    frame.setSize(w, h, 20 * this.mapScale );
    frame.fill = false;
    frame.setOutLine('#ffffff', lineW);
    frame.setScaleXY(this.mapScale);
    frame.x = this.canvasWidth / 2 - w * this.mapScale / 2;
    frame.y = this.canvasHeight / 2 - h * this.mapScale / 2 - 20 * this.mapScale;
    this.teacherPageArr.push(frame);


    const pageShowNum = 5;
    const itemH = h - lineW;
    const baseY = lineW / 2;
    for (let i = 0; i < pageShowNum; i ++) {

      const listItem = new ShapeRect();
      listItem.setSize( w * 0.96, itemH / pageShowNum * 1);
      listItem.x = (w - listItem.width) / 2;
      listItem.y = baseY + i * itemH / pageShowNum;
      listItem.alpha = 0;
      frame.addChild(listItem);


      const labelNum = new Label();
      labelNum.textAlign = 'center';
      labelNum.fontColor = '#ffffff';
      labelNum.fontName = 'BRLNSDB';
      labelNum.fontSize = 50;
      labelNum.text = i.toString();
      labelNum.x = 50;
      labelNum.y = listItem.height / 2;
      listItem.addChild(labelNum);

      const labelName = new Label();
      labelName.textAlign = 'center';
      labelName.fontColor = '#ffffff';
      // labelName.fontName = 'BRLNSDB';
      labelName.fontSize = 40;
      labelName.text = '张三';
      labelName.x = 220;
      labelName.y = listItem.height / 2;
      listItem.addChild(labelName);

      const labelScore = new Label();
      labelScore.textAlign = 'center';
      labelScore.fontColor = '#ffffff';
      // labelScore.fontName = 'BRLNSDB';
      labelScore.fontSize = 35;
      labelScore.text = Math.floor( Math.random() * 100 ).toString();
      labelScore.x = 410;
      labelScore.y = listItem.height / 2;
      listItem.addChild(labelScore);

      // const labelFinish = new Label();
      // labelFinish.textAlign = 'center';
      // labelFinish.fontColor = '#00ff00';
      // labelFinish.fontName = 'BRLNSDB';
      // labelFinish.fontSize = 23;
      // labelFinish.text = 'finish';
      // labelFinish.x = listItem.width - 30;
      // labelFinish.y = listItem.height / 2;
      // listItem.addChild(labelFinish);

      const labelFinish = new MySprite();
      labelFinish.init(this.images.get('t_right'));
      labelFinish.setScaleXY(0.07);
      labelFinish.x = listItem.width - 30;
      labelFinish.y = listItem.height / 2;
      listItem.addChild(labelFinish);



      if (i != pageShowNum - 1) {
        const line = new ShapeRect();
        line.setSize(listItem.width, lineW);
        line.fillColor = '#ffffff';
        line.y = listItem.height;
        listItem.addChild(line);
      }

      listItem['num'] = labelNum;
      listItem['name'] = labelName;
      listItem['score'] = labelScore;
      listItem['finish'] = labelFinish;

      labelNum.visible = false;
      labelName.visible = false;
      labelScore.visible = false;
      labelFinish.visible = false;

      this.teacherPageListArr.push(listItem);

    }


    const arrowL = new MySprite();
    arrowL.init(this.images.get('t_arrow'));
    arrowL.setScaleXY(this.mapScale * 0.17);
    arrowL.x = this.canvasWidth / 2 - w * 0.3 * this.mapScale;
    arrowL.y = frame.y + frame.height * frame.scaleY + 50 * this.mapScale;
    this.arrowL = arrowL;
    this.teacherPageArr.push(arrowL);



    const arrowR = new MySprite();
    arrowR.init(this.images.get('t_arrow'));
    arrowR.setScaleXY(this.mapScale * 0.17);
    arrowR.x = this.canvasWidth / 2 + w * 0.3 * this.mapScale;
    arrowR.y = frame.y + frame.height * frame.scaleY + 50 * this.mapScale;
    arrowR.scaleX *= -1;
    this.arrowR = arrowR;
    this.teacherPageArr.push(arrowR);

    const pageLabel = new Label();
    pageLabel.textAlign = 'center';
    pageLabel.fontColor = '#ffffff';
    pageLabel.fontName = 'BRLNSDB';
    pageLabel.fontSize = 40 * this.mapScale;
    pageLabel.text = '1 / 1';
    pageLabel.x = this.canvasWidth / 2;
    pageLabel.y = arrowL.y;
    this.teacherPageLabel = pageLabel;
    this.teacherPageArr.push(pageLabel);

    this.curTeacherPage = 1;
  }


  addTeacherPageData(data) {

    let hasFlag = false;
    for (let i = 0; i < this.scoreDataArr.length; i++) {
      if (data.user.uuid == this.scoreDataArr[i].user.uuid) {
        // data.updateTime = new Date().getTime();
        // this.scoreDataArr[i] = data;
        // hasFlag = true;
        // break;

        return;
      }
    }
    if (!hasFlag) {
      const maxScore = 5; // 最大分数 依照名次逐渐降低 最低1分
      data.score = maxScore - this.scoreDataArr.length;
      if (data.score < 1) {
        data.score = 1;
      }

      data.finish = true;
      data.updateTime = new Date().getTime();

      this.scoreDataArr.push(data);
    }




    this.scoreDataArr.sort((a, b) => {

      if (a.score == b.score) {
        return a.updateTime - b.updateTime;
      } else {
        return b.score - a.score;
      }

    });



    const pageListNum = 5;
    this.totalTeacherPage = Math.ceil(this.scoreDataArr.length / pageListNum);

    this.refreshTeacherPage();
    // console.log('this.scoreDataArr.length:', this.scoreDataArr.length);

  }

  addStuRightRankData(rightData) {

    console.log('in addStuRightRankData : ', rightData);
    // const duration = new Date().getTime() - this.startDate.getTime();
    this.setRankDataDefaultValue(rightData);

    let rankData = this.statisticsManager.getOneRankData(rightData.uuid);
    if (!rankData) {
      console.log('!rankData 1:', rightData);
      rankData = {};
      rankData.duration = 0;
      rankData.wrongArr = [];
    } else {
      console.log(' has rankData 1:', rankData);
    }

    // console.log('rankData.wrongArr : ', rankData.wrongArr);

    console.log('rankData.duration:' , rankData.duration);
    rankData.duration += rightData.duration;
    console.log('rankData.duration:' , rankData.duration);

    rankData.progressStr = rightData.progressStr;
    rankData.uuid = rightData.user.uuid;
    rankData.name = rightData.user.nick_name;

    rankData.wrongNum = rankData.wrongArr.length;
    rankData.rightNum = this.roleIndex + 1 - rankData.wrongNum;

    // console.log('this.roleIndex : ', this.roleIndex );
    // console.log('rightData.wrongNum : ', rightData.wrongNum );
    //
    // console.log('need send 1---- rankData: ', rankData);

    console.log('1~~rankData: ', rankData);

    this.checkDataIsFinish(rankData);
    this.statisticsManager.addRankDataToList(rankData);

  }

  refreshTeacherPage() {

    let tmpSpr = '+';
    if (this.gameEndFlag) {
      tmpSpr = '';
    }
    const pageNum = 5;
    const startIndex = (this.curTeacherPage - 1) * pageNum;
    const dataArr = this.scoreDataArr.slice(startIndex, startIndex + pageNum);
    for (let i = 0; i < this.teacherPageListArr.length; i++) {

      const list = this.teacherPageListArr[i];
      if (dataArr[i]) {
        list.num.visible = true;
        list.name.visible = true;
        list.score.visible = true;
        list.finish.visible = dataArr[i].finish;

        list.num.text = startIndex + i + 1;
        list.name.text = dataArr[i].user.nick_name.toString();
        list.score.text = tmpSpr + dataArr[i].score.toString();


      } else {
        list.num.visible = false;
        list.name.visible = false;
        list.score.visible = false;
        list.finish.visible = false;
      }
    }

    this.teacherPageLabel.text = this.curTeacherPage + ' / ' + this.totalTeacherPage;

  }

  changePage(value) {
    if (value < 0 && this.curTeacherPage > 1) {
      this.curTeacherPage --;
      this.refreshTeacherPage();
    }

    if (value > 0 && this.curTeacherPage < this.totalTeacherPage) {
      this.curTeacherPage ++;
      this.refreshTeacherPage();
    }
  }









  initServerRole() {

    // const arr = [];
    // if (this.serverAllUser) {
    //   for (let i = 0; i < this.serverAllUser.length; i++) {
    //     arr.push(this.serverAllUser[i].user);
    //   }
    // }
    //
    // this.initRole(arr);


    if (this.serverAllUser) {
      this.syncAllUser(this.serverAllUser);
    } else {
      this.initRole();
    }

  }


  test() {




    const boardRect = this.artboardSmall.boardRect.getBoundingBox();

    const {drawData, rectW} = {"drawData":[{"color":"#7a3918","lineW":3.29,"pointArr":[[5,3],[7,3],[9,3],[11,4],[13,4],[14,5],[17,6],[20,7],[23,9],[25,9],[28,11],[30,12],[32,13],[35,14],[38,15],[39,16],[43,18],[46,19],[49,21],[52,22],[55,24],[58,25],[61,26],[65,28],[68,29],[72,31],[75,33],[79,34],[83,36],[87,38],[91,40],[94,42],[98,43],[102,45],[105,47],[109,48],[113,50],[117,52],[122,54],[128,56],[133,58],[139,60],[145,62],[152,64],[164,68],[172,69],[182,71],[190,72],[200,74],[211,76],[223,77],[235,79],[240,80],[257,81],[269,83],[279,84],[284,85],[294,85],[304,87],[320,88],[329,89],[334,89],[343,90],[351,91],[358,91],[365,91],[371,92],[377,92],[382,92],[388,92],[393,92],[398,92],[404,92],[408,92],[413,92],[419,91],[426,91],[432,89],[438,89],[445,88],[452,87],[458,86],[464,85],[470,84],[475,83],[480,81],[484,80],[486,79],[489,78],[492,77],[495,76],[497,75],[499,74],[500,73],[502,72],[503,71],[505,70],[506,69],[507,68],[508,67],[509,66],[510,65],[511,63],[512,62],[513,61],[514,60],[515,59],[516,58],[518,57],[519,55],[520,54],[521,53],[522,52],[523,51],[524,50],[525,48],[526,47],[527,45],[529,43],[530,41],[531,39],[533,38],[534,37],[535,36],[536,34],[538,33],[539,32],[540,30],[541,29],[542,27],[544,26],[545,24],[546,23],[547,22],[548,21],[549,20],[550,19],[551,18],[552,17],[553,16],[553,14],[554,13],[555,12],[556,11],[557,10],[558,8],[559,7],[560,6]]},{"color":"#1287f1","lineW":3.29,"pointArr":[[557,3],[555,3],[553,3],[551,3],[548,3],[546,3],[543,3],[541,3],[539,3],[537,4],[536,5],[533,6],[532,7],[530,7],[529,8],[528,9],[526,10],[524,11],[523,12],[522,13],[519,14],[518,15],[517,16],[516,17],[515,18],[514,19],[513,20],[512,21],[511,22],[510,23],[509,24],[508,25],[507,26],[506,27],[505,30],[504,31],[503,33],[502,36],[501,38],[500,41],[499,43],[498,45],[497,48],[496,50],[495,53],[494,57],[493,59],[492,62],[491,65],[490,69],[489,72],[488,76],[487,79],[486,82],[485,85],[484,88],[483,92],[483,95],[482,98],[481,102],[481,106],[480,110],[479,114],[478,118],[478,122],[477,126],[477,129],[476,133],[476,137],[476,141],[476,145],[476,148],[475,152],[475,155],[475,158],[474,162],[474,165],[474,169],[474,172],[474,177],[474,180],[474,184],[474,187],[474,192],[474,195],[474,199],[474,202],[474,206],[474,209],[474,213],[474,217],[474,219],[474,221],[474,224],[474,227],[475,230],[475,233],[475,235],[476,237],[477,239],[477,241],[478,243],[479,245],[479,247],[480,248],[481,250],[482,252],[483,254],[484,255],[484,257],[485,258],[486,260],[487,261],[488,262],[489,263],[490,265],[491,266],[492,267],[494,269],[495,270],[497,271],[499,273],[500,274],[501,275],[502,276],[504,276],[505,277],[506,278],[508,280],[509,281],[511,282],[512,283],[513,284],[515,285],[516,286],[518,287],[520,288],[521,289],[523,290],[524,291],[525,292],[526,293],[527,294],[529,295],[531,296],[532,297],[533,298],[534,299],[536,299],[537,300],[538,301],[539,302],[541,302],[542,303],[544,304],[546,304],[547,305],[548,306],[550,306],[551,307],[552,308],[553,309],[555,309],[556,310],[554,310]]},{"color":"#ff3e4c","lineW":3.29,"pointArr":[[553,303],[552,302],[551,301],[549,299],[547,297],[545,295],[543,293],[540,291],[537,290],[536,288],[532,285],[530,284],[528,283],[525,281],[523,280],[522,279],[519,277],[516,275],[514,274],[512,273],[510,272],[506,271],[503,270],[500,268],[497,267],[494,266],[492,264],[489,263],[486,262],[483,261],[479,260],[475,258],[472,257],[467,256],[464,255],[459,253],[455,251],[450,250],[445,248],[439,247],[434,245],[427,243],[422,241],[416,239],[410,237],[404,235],[398,234],[391,232],[384,230],[378,229],[372,227],[366,225],[360,223],[354,222],[347,220],[340,218],[334,217],[328,215],[322,214],[316,212],[310,211],[304,210],[298,209],[292,209],[287,208],[282,207],[278,207],[273,206],[269,206],[264,205],[260,205],[256,204],[252,204],[248,204],[244,204],[241,204],[239,204],[234,204],[230,204],[227,204],[223,204],[219,204],[215,204],[211,204],[209,204],[205,204],[202,205],[197,206],[193,207],[189,207],[188,208],[182,209],[176,211],[174,211],[171,212],[169,213],[166,213],[164,214],[162,215],[158,216],[157,217],[155,218],[153,218],[150,220],[146,222],[143,223],[142,224],[140,225],[138,225],[136,227],[134,227],[132,228],[130,229],[128,230],[127,231],[125,232],[124,233],[122,234],[120,235],[118,236],[115,238],[113,238],[111,239],[109,241],[107,241],[105,242],[103,244],[102,245],[100,245],[98,246],[96,248],[94,249],[92,250],[90,251],[88,252],[86,253],[84,254],[81,256],[80,257],[78,258],[76,259],[74,260],[72,261],[71,262],[69,263],[68,264],[66,265],[65,266],[63,267],[62,268],[60,269],[59,270],[58,271],[56,272],[55,273],[53,274],[52,275],[51,276],[49,277],[48,278],[47,279],[46,280],[44,281],[43,282],[42,283],[41,284],[40,285],[39,286],[38,287],[37,288],[36,289],[35,290],[34,291],[33,292],[32,293],[31,294],[30,295],[29,296],[28,297],[27,298],[26,299],[25,300],[24,301],[23,302],[21,303],[19,304],[18,305],[16,305],[15,306],[13,307],[12,308],[10,308],[9,309],[8,310],[6,310],[5,311],[3,311],[2,312]]},{"color":"#a03fed","lineW":3.29,"pointArr":[[6,304],[8,304],[10,304],[12,304],[15,304],[18,304],[20,304],[22,303],[24,303],[25,302],[27,302],[29,301],[30,300],[32,299],[34,298],[36,297],[37,296],[39,295],[41,294],[43,293],[44,291],[46,290],[47,289],[49,287],[51,284],[52,283],[53,281],[56,278],[59,273],[60,270],[61,267],[63,265],[64,261],[66,258],[67,254],[68,250],[69,245],[71,240],[72,234],[74,229],[75,223],[75,216],[76,210],[77,203],[77,197],[77,190],[77,183],[77,176],[77,169],[77,163],[77,157],[77,151],[77,145],[77,139],[77,133],[76,127],[75,122],[74,118],[73,113],[72,108],[71,104],[70,100],[69,96],[68,93],[68,91],[67,88],[65,85],[64,83],[63,81],[62,79],[61,78],[60,77],[59,75],[58,74],[57,71],[55,70],[55,68],[54,67],[53,65],[52,64],[51,63],[50,61],[48,60],[47,58],[46,56],[45,53],[43,51],[42,50],[40,46],[37,41],[36,38],[35,35],[34,34],[33,32],[32,30],[31,28],[30,27],[29,25],[28,23],[27,22],[26,20],[25,18],[24,17],[23,16],[22,15],[21,14],[20,13],[19,12],[18,11],[16,11],[15,10],[13,9],[11,9],[9,9],[8,8],[7,7],[6,6],[5,5],[4,4],[3,3]]}],"rectW":563.7328124999999};
    const baseRectW = rectW;

    // const baseRect = {"x":219,"y":280,"width":892,"height":498};
    const s = boardRect.width / baseRectW;
    // console.log('s: ', s);
    const serverData = drawData;

    // console.log('boardRect.width', boardRect.width);
    // console.log('baseRect.width', baseRect.width);

    for (let i = 0; i < serverData.length; i++) {

      const lineData = serverData[i];
      const line = new Line();
      line.init();
      line.width = boardRect.width / s;
      line.height = boardRect.height / s;
      line.anchorX = 0;
      line.anchorY = 0;
      line.x = boardRect.x;
      line.y = boardRect.y;
      line.setScaleXY(s);

      line.lineWidth = lineData.lineW;
      line.lineColor = lineData.color;

      // for (let j = 0; j < lineData.pointArr.length; j++) {
      //   lineData.pointArr[j][0] *= s;
      //   lineData.pointArr[j][1] *= s;
      //
      // }

      line._pointArr = lineData.pointArr;


      this.guessPageArr.push(line);


      // line.x = baseRect.x;
      // line.y = baseRect.y;
      // this.renderArr.push(line);

    }

    // this.guessFlag = false;

  }




  drawSmallArtboard(data) {


    if (!this.guessLineArr) {
      this.guessLineArr = [];
    }

    const boardRect = this.artboardSmall.boardRect.getBoundingBox();

    const {drawData, rectW} = data;
    const baseRectW = rectW;

    const s = boardRect.width / baseRectW;
    const serverData = drawData;

    let startIndex = this.guessLineArr.length - 1;
    if (startIndex < 0) {
      startIndex = 0;
    }

    if (serverData.length < this.guessLineArr.length) {
      this.guessLineArr.length = serverData.length;
    }

    // const startIndex = 0;

    for (let i = startIndex; i < serverData.length; i++) {


      const lineData = serverData[i];


      // if (this.guessLineArr[i]) {
      //   this.guessLineArr._pointArr = lineData.pointArr;
      // } else {

        const line = new Line();
        line._pointS = s;
        line.init();
        line.anchorX = 0;
        line.anchorY = 0;
        line.x = boardRect.x;
        line.y = boardRect.y;
        // line.setScaleXY(s);


        line.lineWidth = Math.round(lineData.lineW * s * 100) / 100;
        line.lineColor = lineData.color;

        line._pointArr = lineData.pointArr;
      //
      //   this.guessLineArr.push(line);
      // }

      this.guessLineArr[i] = line;


    }

    console.log('guessLineArr: ', this.guessLineArr);


  }





  initCoverPage() {

    this.coverPageArr = [];

    const cover = new MySprite();
    cover.init(this.images.get('cover'));
    const sx = this.canvasWidth / this.canvasBaseW;
    const sy = this.canvasHeight / this.canvasBaseH;
    const s = Math.max(sx, sy);
    cover.setScaleXY(s);

    cover.x = this.canvasWidth / 2;
    cover.y = 0;
    cover.anchorY = 0;

    this.coverPageArr.push(cover);



    if (this.teachFlag) {
      const startBtn = new MySprite();
      startBtn.init(this.images.get('start_btn'));
      startBtn.setScaleXY(this.mapScale);
      startBtn.x = this.canvasWidth - 200 * this.mapScale;
      startBtn.y = this.canvasHeight - 100 * this.mapScale;
      this.coverPageArr.push(startBtn);

      this.startBtn = startBtn;
    } else {

      const shapeBg = new ShapeRectNew();
      const lenW = 400 * this.mapScale;
      shapeBg.setSize(lenW, lenW / 3 * 1.5, 30 * this.mapScale);
      shapeBg.alpha = 0.5;
      shapeBg.fillColor = '#000000';
      shapeBg.x = this.canvasWidth / 2 - shapeBg.width / 2;
      shapeBg.y = this.canvasHeight / 2 - shapeBg.height / 2;
      this.coverPageArr.push(shapeBg);
      this.startBtn = shapeBg;



      const label = new Label();
      label.fontName = 'BRLNSDB';
      label.fontColor = '#ffffff';
      label.fontSize = 75;
      label.textAlign = 'center';
      label.x = shapeBg.width / 2;
      label.y = shapeBg.height / 2;
      label.setScaleXY(this.mapScale);
      shapeBg.addChild(label);

      // if (this.teachFlag) {
      //   label.text = 'start';
      // } else {
        label.text = 'ready ..';
      // }

    }

  }

  initCurRole() {

    this.curRole = this.roleArr[this.roleIndex];
    this.drawIcon.x = this.curRole.x;

  }

  initCurView() {




    if (this.curRole.data.uuid == this.uuid) {
      this.guessFlag = false;
      if (this.lineArr) {
        this.lineArr.length = 0;
      }

      this.resetDrawView();
      this.addServerSender();

      this.playAudio('tip');

    } else {
      this.guessFlag = true;
      if (this.guessLineArr) {
        this.guessLineArr.length = 0;
      }

      this.resetGuessView();


    }

  }


  resetGuessView() {

    this.initGuessView();
    this.cleanRoleRight();

  }

  resetDrawView() {

    this.refreshDrawWordLabel();
    this.cleanRoleRight();

  }

  cleanRoleRight() {
    if (this.roleArr && this.roleArr.length > 0) {
      for (let i = 0; i < this.roleArr.length; i++) {
        this.roleArr[i].rightIcon.visible = false;
      }
    }
  }

  refreshDrawWordLabel() {
    const data = this.wordArr[this.curWordIndex];

    this.drawWordLabel.text = data.word;


    const wordBg = this.drawWordBg;
    const wordBgOffX = 30;
    const wordBgH = 50;

    const word = wordBg.label;
    word.text = data.word;
    // word.textAlign = 'center';
    // word.fontColor = '#472600';
    // word.fontName = 'BRLNSDB';
    // word.anchorX = 0;
    // word.fontSize = 38;
    word.refreshSize();
    word.x = word.width / 2 + wordBgOffX;
    word.y = wordBgH / 2;
    // wordBg.addChild(word);

    wordBg.setSize(word.width + wordBgOffX * 2, wordBgH, 25);

    wordBg.x = - wordBg.width / 2;
    wordBg.y = - 140;
    // wordBg['label'] = word;
  }



  initMask() {
    const mask = new ShapeRect();
    mask.setSize(this.canvasWidth, this.canvasHeight);
    mask.fillColor = '#000000';
    mask.alpha = 0;
    mask.visible = false;
    this.maskLayer = mask;
  }

  countdownDrawStart() {

    this.canTouch = false;

    const id = setInterval(() => {

      if (this.artboard.countdown <= 1) {

        clearInterval(id);
        this.startDraw();

        this.canTouch = true;
        return;
      }

      this.artboard.countdown --;

      const key = 'num_' + this.artboard.countdown;
      this.artboard.numSpr.init(this.images.get(key));
    }, 1000);
    this.cleanId = id;
  }

  countdownGuessStart() {

    this.canTouch = false;

    const id = setInterval(() => {

      if (this.artboardSmall.countdown <= 1) {

        clearInterval(id);
        this.startGuess();

        this.canTouch = true;
        return;
      }

      this.artboardSmall.countdown --;

      const key = 'num_' + this.artboardSmall.countdown;
      this.artboardSmall.numSpr.init(this.images.get(key));
    }, 1000);

    this.cleanId = id;
  }

  startGuess() {
    this.artboardSmall.numSpr.visible = false;

    const data = this.wordArr[this.curWordIndex];
    this.curDrawTime = data.time;
    this.totalDrawTime = data.time;
    this.clockStartFlag = true;
    this.lastTime = 0;
  }



  initGuessView() {

    // this.guessFlag = true;

    this.guessPageArr = [];


    const bg = new MySprite();
    bg.init(this.images.get('bg'));
    const sx = this.canvasWidth / this.canvasBaseW;
    const sy = this.canvasHeight / this.canvasBaseH;
    const s = Math.max(sx, sy);
    bg.setScaleXY(s);
    bg.x = this.canvasWidth / 2;
    bg.y = this.canvasHeight / 2;
    this.guessPageArr.push(bg);



    // const title = new MySprite();
    // title.init(this.images.get('title'));
    // title.setScaleXY(this.mapScale);
    // title.x = this.canvasWidth / 2;
    // title.y = this.canvasHeight / 12;
    // this.guessPageArr.push(title);

    const guessWordBg = new MySprite();
    guessWordBg.init(this.images.get('text_guess'), 0, 0);
    guessWordBg.setScaleXY(this.mapScale);
    guessWordBg.x = 100 * this.mapScale;
    guessWordBg.y = this.clockBg.y + 60 * this.mapScale;
    this.guessPageArr.push(guessWordBg);
    this.guessWordBg = guessWordBg;

    const wordBgLight = new MySprite();
    wordBgLight.init(this.images.get('text_guess_2'));
    guessWordBg.addChild(wordBgLight);
    wordBgLight.x = guessWordBg.width / 2;
    wordBgLight.y = guessWordBg.height / 2;
    wordBgLight.alpha = 0;
    guessWordBg.addChild(wordBgLight);
    guessWordBg['light'] = wordBgLight;

    const guessLabel = new Label();
    guessLabel.text = '';
    guessLabel.fontSize = 48;
    guessLabel.fontName = 'BRLNSDB';
    guessLabel.fontColor = '#472600';
    guessLabel.textAlign = 'center';
    guessLabel.x = guessWordBg.width / 2;
    guessLabel.y = guessWordBg.height / 2;
    guessWordBg.addChild(guessLabel);
    this.guessLabel = guessLabel;


    const artboard = new MySprite();
    artboard.init(this.images.get('artboard_guess'));
    artboard.setScaleXY(this.mapScale);
    artboard.x = guessWordBg.x + guessWordBg.width / 2 * guessWordBg.scaleX;
    artboard.y = guessWordBg.y + 300 * this.mapScale;
    this.guessPageArr.push(artboard);
    this.artboardSmall = artboard;

    const bigRect = this.artboard['boardRect'];
    const bigRectRate = bigRect.width / bigRect.height;
    const rectOffX = 30;
    const rectOffY = 80;

    const smallRect = new ShapeRect();
    smallRect.setSize(artboard.width - rectOffX * 2, (artboard.width - rectOffX * 2) / bigRectRate );
    smallRect.x = -artboard.width / 2 + rectOffX;
    smallRect.y = -artboard.height / 2 + rectOffY;
    // smallRect.alpha = 0.3;
    smallRect.visible = false;
    artboard.addChild(smallRect);
    artboard['boardRect'] = smallRect;

    const tipLabel = new Label();
    if (this.roleArr && this.roleArr[this.roleIndex]) {
      tipLabel.text = this.roleArr[this.roleIndex].data.nick_name + ' is drawing';
    }
    tipLabel.fontSize = 36;
    // tipLabel.fontName = 'BRLNSDB';
    tipLabel.fontColor = '#b06e52';
    tipLabel.textAlign = 'center';
    tipLabel.fontWeight = 900;
    tipLabel.y = -185;
    artboard.addChild(tipLabel);
    artboard['tipLabel'] = tipLabel;


    const numSpr = new MySprite();
    numSpr.init(this.images.get('num_3'));
    numSpr.y = 15;
    artboard.addChild(numSpr);
    artboard['numSpr'] = numSpr;
    artboard['countdown'] = 3;



    const btnOK = new MySprite();
    btnOK.init(this.images.get('btn_ok'));
    btnOK.setScaleXY(this.mapScale);
    btnOK.x = this.canvasWidth - btnOK.width / 2 * this.mapScale - 10 * this.mapScale;
    btnOK.y = artboard.y + 170 * this.mapScale;
    this.guessPageArr.push(btnOK);
    this.guessOkBtn = btnOK;


    const btnCancle = new MySprite();
    btnCancle.init(this.images.get('btn_cancle'));
    btnCancle.setScaleXY(this.mapScale);
    btnCancle.x = btnOK.x - btnOK.width / 2 * this.mapScale - 50 * this.mapScale;
    btnCancle.y = btnOK.y;
    this.guessPageArr.push(btnCancle);
    this.guessCancleBtn = btnCancle;



    this.guessWordArr = [];

    const data = this.wordArr[this.curWordIndex];
    let len = 169 * this.mapScale;
    let bgS = 1;
    let row = 2;
    let col = 3;
    let offX = btnCancle.x - btnCancle.width / 2 * btnCancle.scaleX;
    let offY = guessWordBg.y ;
    let disW = 10 * this.mapScale;
    let disH = 15 * this.mapScale;

    this.guessWordOffX = offX;
    this.guessWordOffY = offY;
    // const bg = new MySprite();

    const word = data.word;
    let tmpArr = word.split('');
    let tmpIndex = 0;
    tmpArr = randomSortByArr(tmpArr);


    if (tmpArr.length <= 6) {

    } else if (tmpArr.length <= 12) {
      len = 130 * this.mapScale;
      bgS = 130 / 169;
      row = 3;
      col = 4;
      offX = btnCancle.x - btnCancle.width / 2 * btnCancle.scaleX;
      offY = guessWordBg.y ;
      disW = 1 * this.mapScale;
      disH = 3 * this.mapScale;
    } else if (tmpArr.length <= 20) {
      len = 100 * this.mapScale;
      bgS = 100 / 169;
      row = 4;
      col = 5;
      offX = btnCancle.x - btnCancle.width / 2 * btnCancle.scaleX;
      offY = guessWordBg.y ;
      disW = 0 * this.mapScale;
      disH = 0 * this.mapScale;
    } else {
      return;
    }

    for (let i = 0; i < row; i++) {
      for (let j = 0; j < col; j++) {

        const letter = tmpArr[tmpIndex];
        if (letter) {
          const letterBg = new MySprite();
          letterBg.init(this.images.get('letter_bg'), 0, 0);
          letterBg.setScaleXY(this.mapScale * bgS);
          letterBg.x = offX + (len + disW) * j;
          letterBg.y = offY + (len + disH) * i;
          this.guessWordArr.push(letterBg);

          const letterLabel = new Label();
          letterLabel.text = letter;
          letterLabel.textAlign = 'center';
          letterLabel.fontColor = '#ffffff';
          letterLabel.fontName = 'BRLNSDB';
          // letterLabel.anchorX = 0;
          letterLabel.fontSize = 72;
          letterLabel.x = letterBg.width / 2;
          letterLabel.y = letterBg.height / 2 - 10;
          letterLabel.refreshSize();
          letterBg.addChild(letterLabel);
          letterBg['text'] = letter;
        }

        tmpIndex ++;
      }
    }



  }





  initBg() {

    const bg = new MySprite();
    bg.init(this.images.get('bg'));
    const sx = this.canvasWidth / this.canvasBaseW;
    const sy = this.canvasHeight / this.canvasBaseH;
    const s = Math.max(sx, sy);
    bg.setScaleXY(s);
    bg.x = this.canvasWidth / 2;
    bg.y = this.canvasHeight / 2;
    this.renderArr.push(bg);





    // const title = new MySprite();
    // title.init(this.images.get('title'));
    // title.setScaleXY(this.mapScale);
    // title.x = this.canvasWidth / 2;
    // title.y = this.canvasHeight / 12;
    // this.renderArr.push(title);







    const artboard = new MySprite();
    artboard.init(this.images.get('artboard'));
    artboard.setScaleXY(this.mapScale);
    artboard.x = this.canvasWidth / 2;
    artboard.y = this.canvasHeight / 1.6;
    this.artboard = artboard;
    this.renderArr.push(artboard);

    const artboardRect = new ShapeRect();
    const rectOffX = 29;
    const rectOffY = 17;
    artboardRect.setSize(artboard.width - 58, artboard.height - 57);
    artboardRect.x = -artboard.width / 2 + rectOffX;
    artboardRect.y = -artboard.height / 2 + rectOffY;
    // artboardRect.alpha = 0.3;
    artboardRect.visible = false;
    artboard.addChild(artboardRect);
    artboard['boardRect'] = artboardRect;




    const yourTurn = new MySprite();
    yourTurn.init(this.images.get('your_turn'));
    yourTurn.y = -188;
    artboard.addChild(yourTurn);

    const wordBg = new ShapeRectNew();
    const wordBgOffX = 30;
    const wordBgH = 50;
    wordBg.fillColor = '#000000';
    wordBg.alpha = 0.1;
    artboard.addChild(wordBg);

    const data = this.wordArr[this.curWordIndex];
    const word = new Label();
    word.text = data.word;
    word.textAlign = 'center';
    word.fontColor = '#472600';
    word.fontName = 'BRLNSDB';
    word.anchorX = 0;
    word.fontSize = 38;
    word.refreshSize();
    word.x = word.width / 2 + wordBgOffX;
    word.y = wordBgH / 2;
    wordBg.addChild(word);

    wordBg.setSize(word.width + wordBgOffX * 2, wordBgH, 25);

    wordBg.x = - wordBg.width / 2;
    wordBg.y = - 140;
    wordBg['label'] = word;

    this.drawWordBg = wordBg;


    const numSpr = new MySprite();
    numSpr.init(this.images.get('num_3'));
    numSpr.y = 60;
    artboard.addChild(numSpr);

    const tipLabel = new Label();
    tipLabel.text = `Let's draw: `;
    tipLabel.fontColor = '#b06e52';
    tipLabel.fontName = 'BRLNSDB';
    tipLabel.fontSize = 30;
    tipLabel.anchorX = 0;
    tipLabel.refreshSize();
    tipLabel.x = -artboard.width / 2 + 50;
    tipLabel.y = -artboard.height / 2 + 40;
    artboard.addChild(tipLabel);
    tipLabel.visible = false;
    tipLabel.childDepandAlpha = true;

    const wordLabel = new Label();
    wordLabel.text = data.word;
    wordLabel.fontColor = '#472600';
    wordLabel.fontName = 'BRLNSDB';
    wordLabel.fontSize = 30;
    wordLabel.anchorX = 0;
    wordLabel.refreshSize();
    wordLabel.x = tipLabel.width;
    tipLabel.addChild(wordLabel);

    this.drawWordLabel = wordLabel;




    artboard['tip'] = yourTurn;
    artboard['wordBg'] = wordBg;
    artboard['numSpr'] = numSpr;
    artboard['countdown'] = 3;
    artboard['tipLabel'] = tipLabel;




    const clockBg = new MySprite();
    clockBg.init(this.images.get('clock_bg'));
    clockBg.anchorY = 0;
    clockBg.setScaleXY(this.mapScale);
    clockBg.x = 50 * this.mapScale;
    clockBg.y = artboard.y - artboard.height / 2 * artboard.scaleY - 60 * this.mapScale;
    this.clockBg = clockBg;
    // this.renderArr.push(clockBg);

    const clock = new MySprite();
    clock.init(this.images.get('clock'));
    clock.y = 5 + clock.height / 2;
    clockBg.addChild(clock);

    const clockBar = new MySprite();
    clockBar.init(this.images.get('clock_bar_1'));
    clockBar.y = 52;
    clockBar.anchorY = 0;
    clockBar['id'] = '1';
    clockBg.addChild(clockBar);



    this.clockBar = clockBar;


    const cleanBtn = new MySprite();
    cleanBtn.init(this.images.get('clean_btn'));
    cleanBtn.setScaleXY(this.mapScale);
    cleanBtn.x = clockBg.x + 30 * this.mapScale;
    cleanBtn.y = clockBg.y + clockBg.height * clockBg.scaleY + 90 * this.mapScale;
    this.renderArr.push(cleanBtn);
    this.cleanBtn = cleanBtn;



    this.brushArr = [];
    const colorArr = ['#7a3918', '#2eba2f', '#1287f1', '#a03fed', '#ff3e4c'];
    const brushOffY = clockBg.y + 220 * this.mapScale;
    for (let i = 0; i < colorArr.length; i++) {

      const key = 'brush_' + (i + 1);
      const brush = new MySprite();
      brush.init(this.images.get(key));
      brush.setScaleXY(this.mapScale);
      // brush.anchorX = 1;
      brush.x = this.canvasWidth + 1;
      brush.y = brushOffY + i * 80 * this.mapScale;
      brush['baseX'] = brush.x;
      brush['baseY'] = brush.y;
      brush['brushColor'] = colorArr[i];


      const touchRect = new ShapeRect();
      touchRect.setSize(60, 60);
      touchRect.fillColor = '#00ff00';
      brush.addChild(touchRect);
      touchRect.x = -brush.width / 2 + 10;
      touchRect.y = -brush.height / 2 + 10;
      touchRect.alpha = 0;

      brush['touchRect'] = touchRect;


      this.brushArr.push(brush);
      this.renderArr.push(brush);
    }


    this.initCurBrush();
  }

  initCurBrush() {

    this.clickedBrush(this.brushArr[0]);
    // this.curBrush = this.brushArr[0];

  }


  initRole(roleData = null) {


    if (!roleData || roleData.length == 0) {

      // 假数据
      roleData = [];
      for (let i = 0; i < 1; i++) {
        const data = {
          uuid: i,
          nick_name: '学生-' + (i + 1),
          role: 'stu'
        };
        roleData.push(data);
      }
    }

    if (roleData.length > 15) {
      roleData.length = 15;
    }

    for (let i = 0; i < roleData.length; i ++) {
      if (roleData[i].classRole == 'tea') {
        roleData.splice(i , 1);
        break;
      }
    }



    console.log('roleDataP', roleData);

    this.roleData = roleData;

    this.roleArr = [];

    const headW = 64;
    const disW = 5;
    const shapeH = 80;


    const shapeRect = new ShapeRect();

    const offX = headW / 2;
    const offY = shapeH / 2;
    const roleNum = roleData.length; // 3 + Math.floor( Math.random() * 10 );
    for (let i = 0; i < roleNum; i ++) {

      const data = roleData[i];

      const headBg = new MySprite();
      headBg.init(this.images.get('head_bg'));
      headBg.x = offX + i * (disW + headW);
      headBg.y = offY;
      shapeRect.addChild(headBg);

      const headId = i % 12 + 1;  // Math.ceil( Math.random() * 12 );
      const rolePic = new RoundSprite();
      rolePic.init(this.images.get('head_' + headId));
      rolePic.y = -2;
      const rpLen = 50;
      const sx = rpLen / rolePic.width;
      const sy = rpLen / rolePic.height;
      const s = Math.min(sx, sy);
      rolePic.setScaleXY(s);
      // rolePic.setRadius(rolePic.width / 2);


      headBg.addChild(rolePic);

      if (data.connected == false) {
        rolePic.alpha = 0.3;
      }

      const nameBg = new ShapeRectNew();
      nameBg.alpha = 0.3;
      nameBg.setSize(headBg.width * 0.9, headBg.height / 3.5, 5);
      nameBg.fillColor = '#000000';
      nameBg.x = - nameBg.width / 2;
      nameBg.y = headBg.height / 2;
      nameBg.visible = false;
      nameBg.childDepandVisible = false;
      headBg.addChild(nameBg);

      const nameLabel = new Label();
      nameLabel.text = data.nick_name;
      nameLabel.fontColor = '#00a0ed';
      nameLabel.textAlign = 'center';
      // nameLabel.fontName = 'BRLNSDB';
      nameLabel.fontSize = 12;
      nameLabel.x = nameBg.width / 2;
      nameLabel.y = nameBg.height / 2;
      nameBg.addChild(nameLabel);


      if (data.uuid == this.uuid) {
        const me = new MySprite();
        me.init(this.images.get('me'));
        me.x = -headBg.width / 3;
        me.y = -headBg.height / 3;
        headBg.addChild(me);

      }

      this.checkNameLabelWidth(nameLabel, nameBg.width * 0.8);


      const rightIcon = new MySprite();
      rightIcon.init(this.images.get('right_icon'));
      rightIcon.x = headBg.width / 3;
      rightIcon.y = headBg.height / 3;
      rightIcon.visible = false;
      headBg.addChild(rightIcon);
      headBg['rightIcon'] = rightIcon;

      if (this.rightIconObj && this.rightIconObj[data.uuid]) {
        rightIcon.visible = true;
      }

      headBg['data'] = data;
      this.roleArr.push(headBg);

    }

    const totalW = roleNum * headW + (roleNum - 1) * disW;
    shapeRect.setSize(totalW, shapeH);
    shapeRect.setScaleXY(this.mapScale * 1.2);
    shapeRect.x = this.canvasWidth / 2 - shapeRect.width / 2 * shapeRect.scaleX;
    shapeRect.y = this.canvasHeight / 20;
    shapeRect.fillColor = '#ff0000';
    shapeRect.alpha = 0;
    this.roleBg = shapeRect;

    console.log('~~len: ', shapeRect.children.length);



    const drawIcon = new MySprite();
    drawIcon.init(this.images.get('drawing_icon'));
    this.drawIcon = drawIcon;
    this.roleBg.addChild(drawIcon);
    this.drawIcon.anchorY = 0.8;
    // this.renderArr.push(shapeRect);

  }

  checkNameLabelWidth(label, maxW) {
    const arr = label.text.split('');

    label.text = '';
    for (let i = 0; i < arr.length; i++) {
      label.text += arr[i];
      label.refreshSize();
      if ( i < arr.length - 1 && label.width >= maxW) {
        label.text += '..';
        return;
      }
    }
  }







  hideAllBrush() {

    for (let i = 0; i < this.brushArr.length; i++) {
      const brush = this.brushArr[i];
      if (brush != this.curBrush) {
        tweenChange(brush, {x: brush.baseX, y: brush.baseY}, 0.3, null, TWEEN.Easing.Quadratic.Out);

      }
    }
  }

  clickedBrush(brush) {


    if (brush === this.curBrush) {
      return;
    }


    const offX = 40 * this.mapScale;
    const offY = 35.5 * this.mapScale;
    tweenChange(brush, {x: brush.baseX - offX, y: brush.baseY - offY}, 0.15, null, TWEEN.Easing.Quadratic.Out);

    this.curBrush = brush;

    this.hideAllBrush();


  }


  touchDownArtboard() {

    this.brushPointArr = [];

    const rect =  this.artboard.boardRect.getBoundingBox();
    const line = new Line();
    line.width = rect.width;
    line.height = rect.height;
    line.init();

    line.x = rect.x;
    line.y = rect.y;
    line.anchorX = 0;
    line.anchorY = 0;

    line.lineWidth = 5 * this.mapScale;
    line.lineColor = this.curBrush.brushColor.toString();
    // line.setPointArr(this.brushPointArr, this.images.get('brush_line'));
    this.lineArr.push(line);
    this.curLine = line;

    this.brushPointArr.push([Math.round(this.mx), Math.round(this.my)]);
    this.brushDownFlag = true;

  }

  touchMoveArtboard() {

    const checkDis = 8 * this.mapScale;

    const lastP = this.brushPointArr[this.brushPointArr.length - 1];
    const dis = getPosDistance(lastP[0], lastP[1], this.mx, this.my);
    if (dis >= checkDis) {
      this.brushPointArr.push([Math.round(this.mx), Math.round(this.my)]);

      this.curLine.addPoint(Math.round(this.mx - this.curLine.x), Math.round(this.my - this.curLine.y));

      this.checkSendServerDrawChange();
    }
  }

  touchEndArtboard() {
    this.brushDownFlag = false;



    this.curLine = null;
  }

  sendDrawData() {


    const drawData = [];

    const rect = this.artboard.boardRect.getBoundingBox();

    for (let i = 0; i < this.lineArr.length; i++) {
      // const arr = this.lineArr[i]._pointArr;
      //
      // let pointArr = [];
      // for (let j = 0; j < arr.length; j++) {
      //   pointArr.push(arr[j]);
      // }

      const tmpData = {
        color : this.lineArr[i].lineColor,
        lineW:  Math.round(this.lineArr[i].lineWidth * 100) / 100,
        pointArr : this.lineArr[i]._pointArr
      };
      drawData.push(tmpData);
    }

    // console.log(JSON.stringify(drawData));
    // console.log(JSON.stringify(rect));

    const data = {
      drawData,
      rectW: Math.round( rect.width * 100 ) / 100
    };

    // console.log('sendData: ', JSON.stringify(data));

    this.sendServerEvent('drawChange', data);
  }


  cleanBtnClick() {


    this.lineArr.length = 0;
    this.needSendDataFlag = true;
    this.playAudio('clean', true);
  }



  startDraw() {
    const data = this.wordArr[this.curWordIndex];
    this.curDrawTime = data.time;
    this.totalDrawTime = data.time;
    this.clockStartFlag = true;

    this.artboard.tip.visible = false;
    this.artboard.wordBg.visible = false;
    this.artboard.numSpr.visible = false;
    this.artboard.tipLabel.visible = true;
    this.artboard.tip.countdown = 3;


    this.artboard.tipLabel.alpha = 0;
    showItem(this.artboard.tipLabel);
  }


  refreshClockBar() {

    const clockBar = this.clockBar;

    const showRate = Math.round(this.curDrawTime / this.totalDrawTime * 1000) / 1000;
    const showRect = {
      x: 0,
      y: (1 - showRate) * clockBar.height,
      width: clockBar.width,
      height: showRate * clockBar.height
    };
    clockBar.setShowRect(showRect);


    if (showRate < 0.5 && clockBar.id == 1) {
      clockBar.init(this.images.get('clock_bar_2'), clockBar.anchorX, clockBar.anchorY);
      clockBar.id = 2;
    } else if (showRate < 0.25 && clockBar.id == 2) {
      clockBar.init(this.images.get('clock_bar_3'), clockBar.anchorX, clockBar.anchorY);
      clockBar.id = 3;
    }
  }




  timeEnd() {

    this.clockStartFlag = false;
    this.clockBar.visible = false;

    this.canTouch = false;

    if (this.teachFlag) {

      this.sendServerNewRound();
    }


  }

  startNewRound() {

    this.showMaskLayer();
    this.removeServerSender();
  }





  checkSendServerDrawChange() {
    const curDateTime = new Date().getTime();
    if (!this.lastSendTime || curDateTime - this.lastSendTime > this.sendServerDisTime) {
      this.sendDrawData();
      this.lastSendTime = curDateTime;
      this.needSendDataFlag = false;
    } else {
      this.needSendDataFlag = true;
    }
  }

  addServerSender() {

    this.drawSenderId = setInterval(() => {
      if (this.needSendDataFlag) {
        this.checkSendServerDrawChange();
      }
    }, this.sendServerDisTime);
  }

  removeServerSender() {
    clearInterval(this.drawSenderId);
  }


  onServerRoundStart() {
    if (this.guessFlag) {
      this.countdownGuessStart();
    } else {
      this.countdownDrawStart();
    }

    this.playAudio('countdown', true);


  }



  showMaskLayer() {

    this.maskLayer.visible = true;
    this.maskLayer.alpha = 0;

    const showTime = 1;
    tweenChange(this.maskLayer, {alpha: 1}, showTime / 2, () => {

      // this.guessFlag = true;

      // this.roleIndex ++;
      // this.curWordIndex ++;;
      // this.curWordIndex = this.roleIndex;

      if (this.curWordIndex >= this.wordArr.length - 1) {
        // this.curWordIndex = 0;
        // this.wordArr = randomSortByArr(this.wordArr);
        const tmpArr = randomSortByArr(this.wordArr);
        this.wordArr = this.wordArr.concat(tmpArr);
      }


      console.log('check Game end 2, index: ', this.roleIndex);
      console.log('check Game end 2, length: ', this.roleArr.length);
      if (this.roleIndex >= this.roleArr.length) {
        console.log('game end');

        this.gameEnd();
      } else {

        this.initCurRole();
        this.initCurView();

        this.resetClockBar();
      }




      tweenChange(this.maskLayer, {alpha: 0}, showTime / 2, () => {
        this.maskLayer.visible = false;

        if (!this.gameEndFlag) {
          this.onServerRoundStart();
        }

      }, TWEEN.Easing.Quadratic.InOut);

    }, TWEEN.Easing.Quadratic.InOut);
  }

  resetClockBar() {

    this.clockBar.init(this.images.get('clock_bar_1'), this.clockBar.anchorX, this.clockBar.anchorY);
    this.clockBar.id = 1;
    this.clockBar.setShowRect(null);
    this.clockBar.visible = true;
  }

  refreshGuessWord() {


    this.guessWordArr = [];

    const data = this.wordArr[this.curWordIndex];
    let len = 169 * this.mapScale;
    let bgS = 1;
    let row = 2;
    let col = 3;
    let offX = this.guessWordOffX;
    let offY = this.guessWordOffY;
    let disW = 10 * this.mapScale;
    let disH = 15 * this.mapScale;


    const word = data.word;
    let tmpArr = word.split('');
    let tmpIndex = 0;
    tmpArr = randomSortByArr(tmpArr);


    if (tmpArr.length <= 6) {

    } else if (tmpArr.length <= 12) {
      len = 130 * this.mapScale;
      bgS = 130 / 169;
      row = 3;
      col = 4;
      // offX = btnCancle.x - btnCancle.width / 2 * btnCancle.scaleX;
      // offY = guessWordBg.y ;
      disW = 1 * this.mapScale;
      disH = 3 * this.mapScale;
    } else if (tmpArr.length <= 20) {
      len = 100 * this.mapScale;
      bgS = 100 / 169;
      row = 4;
      col = 5;
      // offX = btnCancle.x - btnCancle.width / 2 * btnCancle.scaleX;
      // offY = guessWordBg.y ;
      disW = 0 * this.mapScale;
      disH = 0 * this.mapScale;
    } else {
      return;
    }

    for (let i = 0; i < row; i++) {
      for (let j = 0; j < col; j++) {

        const letter = tmpArr[tmpIndex];
        if (letter) {
          const letterBg = new MySprite();
          letterBg.init(this.images.get('letter_bg'), 0, 0);
          letterBg.setScaleXY(this.mapScale * bgS);
          letterBg.x = offX + (len + disW) * j;
          letterBg.y = offY + (len + disH) * i;
          this.guessWordArr.push(letterBg);

          const letterLabel = new Label();
          letterLabel.text = letter;
          letterLabel.textAlign = 'center';
          letterLabel.fontColor = '#ffffff';
          letterLabel.fontName = 'BRLNSDB';
          // letterLabel.anchorX = 0;
          letterLabel.fontSize = 72;
          letterLabel.x = letterBg.width / 2;
          letterLabel.y = letterBg.height / 2 - 10;
          letterLabel.refreshSize();
          letterBg.addChild(letterLabel);
        }

        tmpIndex ++;
      }
    }

  }

  clickGuessWord(guessWordBg) {

    if (!guessWordBg.visible) {
      return;
    }


    const arr = this.guessWordArr;
    for (let i = 0; i < arr.length; i++) {
      if (arr[i] == guessWordBg) {

        arr[i].visible = false;
        this.guessLabel.text += guessWordBg['text'];
        break;
      }
    }

    this.guessWordBg.light.alpha = 1;
    this.guessWordBg.alpha = 0;
  }




  guessOkBtnClick() {
    const data = this.wordArr[this.curWordIndex];
    if (this.guessLabel.text.length == 0) {
      return;
    }


    if (data.word == this.guessLabel.text) {

      // console.log(" right ");
      this.sendStuRightData();

      this.guessWordBg.img = this.images.get('text_guess_right');
      this.playAudio('right');
    } else {
      // console.log(" wrong ");

      // this.sendStuWrongData();

      this.guessWordBg.img = this.images.get('text_guess_wrong');
      this.playAudio('wrong');
    }




    this.guessWordBg.alpha = 1;
    this.guessWordBg.light.alpha = 0;

    this.guessOkBtn.visible = false;
    this.guessCancleBtn.visible = false;

    this.canTouch = false;

  }


  sendStuRightData() {

    const duration = new Date().getTime() - this.startDate.getTime();
    // this.totalDuration += duration;
    //
    // const wrongId = this.roleIndex + 1;
    // const wIndex = this.wrongArr.indexOf(wrongId);
    // if (wIndex != -1) {
    //   this.wrongArr.splice(wIndex);
    // }

    const sendData = {
      user: this.user,
      duration,
      progressStr : (this.roleIndex + 1) + ' / ' + this.roleArr.length,
    }
    this.sendServerEvent('answerRight', sendData);
  }

  sendStuWrongData() {

    // const duration = new Date().getTime() - this.startDate.getTime();
    // this.totalDuration += duration;
    //
    // const sendData = {
    //   user: this.user,
    //   wrongArr: this.wrongArr,
    //   duration: this.totalDuration
    // }
    // this.sendServerEvent('answerWrong', sendData);
  }

  guessCancleBtnClick() {
    const arr = this.guessWordArr;
    for (let i = 0; i < arr.length; i++) {
      arr[i].visible = true;
    }
    this.guessLabel.text = '';
    this.guessWordBg.alpha = 1;
    this.guessWordBg.light.alpha = 0;

  }


  startBtnClick() {

    const roleData = this.roleData;
    const roleIndex = this.roleIndex;
    const wordArr = this.wordArr;
    const gameResultArr = this.gameResultArr;
    const date = new Date().getTime();



    this.sendServerEvent(this.MESSAGE_START, {startData: {quesNum: this.roleArr.length}, roleData, roleIndex, wordArr, gameResultArr, date, start: true});

    this.canTouch = false;
  }

  sendServerNewRound() {

    const roleData = this.roleData;
    const roleIndex = this.roleIndex + 1;
    const wordArr = this.wordArr;
    const gameResultArr = this.gameResultArr;
    const date = new Date().getTime();

    console.log('gameResultArr: ', gameResultArr);

    const newRoundData = {roleData, roleIndex, wordArr, gameResultArr, date, start: true};

    this.sendOtherRoleData(newRoundData);
  }

  sendOtherRoleData(newRoundData) {

    const roundDuration = this.wordArr[this.curWordIndex].time * 1000;

    for (let i = 0; i < this.curWrongRoleArr.length; i++) {
      const wrongRoleData = this.curWrongRoleArr[i];
      this.setRankDataDefaultValue(wrongRoleData);

      let rankData = this.statisticsManager.getOneRankData(wrongRoleData.uuid);
      if (!rankData) {
        console.log('!rankData 2 : ', wrongRoleData);
        rankData = {};
        rankData.duration = 0;
        rankData.wrongArr = [];
      } else {
        console.log(' has rankData 2 : ', wrongRoleData);
      }

      // console.log('rankData.wrongArr : ', rankData.wrongArr);

      rankData.uuid = wrongRoleData.uuid;
      rankData.name = wrongRoleData.nick_name;

      console.log('rankData.duration:' , rankData.duration);
      rankData.duration += roundDuration;
      console.log('rankData.duration:' , rankData.duration);

      rankData.wrongArr.push(this.roleIndex + 1);

      rankData.wrongNum = rankData.wrongArr.length;
      rankData.rightNum = this.roleIndex + 1 - rankData.wrongNum;
      rankData.progressStr = (this.roleIndex + 1) + ' / ' + this.roleArr.length;

      // console.log('need send 2 ---- rankData: ', rankData);
      //
      // console.log('this.roleIndex : ', this.roleIndex );
      // console.log('rightData.wrongNum : ', rankData.wrongNum );
      //
      console.log('~~rankData: ', rankData);

      this.checkDataIsFinish(rankData);
      this.statisticsManager.addRankDataToList(rankData);
    }


    const rightData = {
      user: this.roleData[this.roleIndex],
      duration: roundDuration,
      progressStr: (this.roleIndex + 1) + ' / ' + this.roleArr.length
    }
    this.addStuRightRankData(rightData)


    newRoundData['rankData'] = this.statisticsManager.rankDataList;
    this.statisticsManager.sendRankDataEvent(newRoundData);
    this.sendServerEvent('newRound', newRoundData);


  }

  setRankDataDefaultValue(data) {
    if (data.user) {
      data.uuid = data.user.uuid;
      data.nick_name = data.user.nick_name;
    }
    if (!data.duration) {
      data.duration = 0;
    }
    if (!data.wrongArr) {
      data.wrongArr = [];
    }
  }

  checkDataIsFinish(rankData) {
    const { rightNum, wrongNum } = rankData;
    if (rightNum + wrongNum >= this.roleData.length) {
      rankData.finish = true;
    }
  }


  gameEnd() {
    this.gameEndFlag = true;

    this.endPageArr = [];

    const bg = new MySprite();
    bg.init(this.images.get('bg'));
    bg.x = this.canvasWidth / 2;
    bg.y = this.canvasHeight / 2;
    const sx = this.canvasWidth / this.canvasBaseW;
    const sy = this.canvasHeight / this.canvasBaseH;
    const s = Math.max(sx, sy);
    bg.setScaleXY(s);
    this.endPageArr.push(bg);


    const title = new MySprite();
    title.init(this.images.get('title'));
    title.setScaleXY(this.mapScale);
    title.x = this.canvasWidth / 2;
    title.y = this.canvasHeight / 12;
    this.endPageArr.push(title);


    this.setResulrView();





    this.canTouch = true;
    this.petalTime = 0;

    this.playAudio('finish');

    this.showEndPatal();

    setTimeout(() => {
      this.showPetalFlag = false;
    }, 5000);


  }

  setResulrView() {

    const scoreObj = {};
    for (let i = 0; i < this.gameResultArr.length; i++) {

      const scoreDataArr = this.gameResultArr[i];

      for (let j = 0; j < scoreDataArr.length; j++) {
        const key = scoreDataArr[j].user.uuid;
        if (!scoreObj[key]) {
          scoreObj[key] = 0;
        }
        scoreObj[key] += Number(scoreDataArr[j].score);
      }
    }


    this.scoreDataArr = [];
    for (let i = 0; i < this.roleData.length; i++) {

      const data = {
        user: this.roleData[i],
        score: scoreObj[this.roleData[i].uuid] || 0,
      }
      this.scoreDataArr.push(data);
    }


    this.scoreDataArr.sort((a, b) => {

      return b.score - a.score;

    });


    const pageListNum = 5;
    this.totalTeacherPage = Math.ceil(this.scoreDataArr.length / pageListNum);

    this.refreshTeacherPage();
  }




  showEndPatal() {

    // this.endPageArr = [];
    this.showPetalFlag = true;
    this.addPetal();

  }



  addPetal() {

    if (!this.showPetalFlag) {
      return;
    }

    const petal = this.getPetal();

    // const petal = new MySprite();
    // petal.init(this.images.get('petal_1'));
    // petal.x = Math.random() * this.canvasWidth;
    // petal.y = Math.random() * this.canvasHeight;
    this.endPageArr.push(petal);

    moveItem(petal, petal.x, this.canvasHeight + petal.height * petal.scaleY, petal['time'], () => {
      removeItemFromArr(this.endPageArr, petal);
    });

    rotateItem(petal, petal['tr'], petal['time']);

    setTimeout(() => {
      this.addPetal();
    }, 0 + this.petalTime);

    this.petalTime +=  5;
  }


  getPetal() {

    // console.log('in getPetal');
    const petal = new MySprite();

    const id = Math.ceil( Math.random() * 3 );
    petal.init(this.images.get('petal_' + id));

    const randomS = (Math.random() * 0.4 + 0.6) * this.mapScale;
    petal.setScaleXY(randomS);

    const randomR = Math.random() * 360;
    petal.rotation = randomR;

    const randomX = Math.random() * this.canvasWidth;
    petal.x = randomX;
    petal.y = -petal.height / 2 * petal.scaleY;

    const randomT = 2 + Math.random() * 5;
    petal['time'] = randomT;

    let randomTR = 360 * Math.random(); // - 180;
    if (Math.random() < 0.5) { randomTR *= -1; }
    petal['tr'] = randomTR;

    return petal;
  }








  mapDown(event) {

    if (!this.canTouch) {
      return;
    }


    if (!this.startFlag) {

      if (this.teachFlag && this.checkClickTarget(this.startBtn)) {
        this.startBtnClick();
      }
      return;
    }



    if (this.teacherPage.visible) {
      if (this.checkClickTarget(this.arrowL)) {
        this.changePage(-1);
      } else if (this.checkClickTarget(this.arrowR)) {
        this.changePage(1);
      }
      return;
    }


    if (this.gameEndFlag) {
      return;
    }

    if (this.guessFlag) {
      for (let i = 0; i < this.guessWordArr.length; i++) {
        if (this.checkClickTarget(this.guessWordArr[i])) {
          this.clickGuessWord(this.guessWordArr[i]);
          return;
        }
      }

      if (this.checkClickTarget(this.guessOkBtn)) {
        this.guessOkBtnClick();
        return;
      }

      if (this.checkClickTarget(this.guessCancleBtn)) {
        this.guessCancleBtnClick();
        return;
      }

      return;
    }


    for (let i = 0; i < this.brushArr.length; i++) {

      const brush = this.brushArr[i];
      if (this.checkClickTarget(brush.touchRect)) {
        this.clickedBrush(brush);
        this.playAudio('brush_change', true);
        return;
      }
    }

    if (this.checkClickTarget(this.artboard.boardRect)) {
      this.touchDownArtboard();
      return;
    }

    if (this.checkClickTarget(this.cleanBtn)) {
      this.cleanBtnClick();
      return;
    }

  }

  mapMove(event) {


    if (this.brushDownFlag) {

      if (this.canTouch && this.checkClickTarget(this.artboard.boardRect)) {
        this.touchMoveArtboard();
      } else {
        this.touchEndArtboard();
      }

    }
  }

  mapUp(event) {
    this.touchEndArtboard();
  }



  setRoleRight(serverData) {
    for (let i = 0; i < this.roleArr.length; i++) {
      const roleData = this.roleArr[i].data;
      if (roleData.uuid == serverData.uuid) {
        this.roleArr[i].rightIcon.visible = true;
      }
    }
  }










  updateTime(t) {
    if (!this.clockStartFlag) {
      return;
    }

    if (this.lastTime && t) {

      const dt = Math.round( (t - this.lastTime) * 100 ) / 100 / 1000;
      this.curDrawTime -= dt;

      if (this.curDrawTime <= 0) { // 结束画画
        // if (this.guessFlag) {
        //
        // } else {
        //   this.drawTimeEnd();
        // }

        this.timeEnd();

        return;
      }
      this.refreshClockBar();
      // console.log('dt :', dt);
    }

    this.lastTime = t;
  }




  update(t = null) {

    // ----------------------------------------------------------
    this.animationId = window.requestAnimationFrame(this.update.bind(this));
    // 清除画布内容
    this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
    // tween 更新动画
    TWEEN.update();
    // ----------------------------------------------------------



    this.updateArr(this.renderArr);
    this.updateArr(this.lineArr);
    // this.updateLineArr();

    this.updateTime(t);

    if (this.guessFlag) {
      this.updateArr(this.guessPageArr);
      this.updateArr(this.guessLineArr);
      this.updateArr(this.guessWordArr);
    }


    this.updateItem(this.clockBg);
    this.updateItem(this.roleBg);


    this.updateArr(this.coverPageArr);

    this.updateArr(this.endPageArr);


    if (this.teacherPage.visible) {
      this.updateArr(this.teacherPageArr);
    }

    if (this.maskLayer.visible) {
      this.updateItem(this.maskLayer);
    }





    this.ctx.drawImage(this.offCanvas, 0, 0);

  }



}
