// Learn cc.Class:
//  - https://docs.cocos.com/creator/manual/en/scripting/class.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

// import { getSprNode } from "./util";
import { getSprNode, playAudioByUrl, showBtnAnima, getScaleRateBy2Node, localPosTolocalPos, randomSortByArr, loadDragonBones, playAudio, showTrebleFirework, getSprNodeByUrl, setSprNodeMaxLen, delayCall, asyncDelay, RandomInt, exchangeNodePos, onHomeworkFinish, getMaxScale, removeFromArr} from "../script/util";

cc.Class({
	extends: cc.Component,

	properties: {
		baseWidth: {
			default: 1920,
			type: cc.Integer
		},
		baseHeight: {
			default: 1200,
			type: cc.Integer
		}
	},

	onLoad() {
		cc.debug.setDisplayStats(false);
		this.initSceneData();
		this.initSize();
	
	},

	initSceneData() {
		this._imageResList = [];
		this._audioResList = [];
		this._animaResList = [];
		this._timeoutIds = [];
		this._intervalIds = [];
	},


	_designSize: null,
	_frameSize: null,
	_mapScaleMin: null,
	_mapScaleMax: null,
	_cocosScale: null,
	canvas: null,
	initSize() {


		// 注意cc.winSize只有在适配后(修改fitHeight/fitWidth后)才能获取到正确的值,因此使用cc.getFrameSize()来获取初始的屏幕大小
		let screen_size = cc.view.getFrameSize().width / cc.view.getFrameSize().height
		let design_size = cc.Canvas.instance.designResolution.width / cc.Canvas.instance.designResolution.height
		let f = screen_size >= design_size
		cc.Canvas.instance.fitHeight = f
		cc.Canvas.instance.fitWidth = !f

		const frameSize = cc.view.getFrameSize();
		this._frameSize = frameSize;

		this._designSize = cc.view.getDesignResolutionSize();

		let sx = cc.winSize.width / frameSize.width;
		let sy = cc.winSize.height / frameSize.height;
		this._cocosScale = Math.min(sx, sy);

		sx = frameSize.width / this._designSize.width;
		sy = frameSize.height / this._designSize.height;
		this._mapScaleMin = Math.min(sx, sy) * this._cocosScale;
		this._mapScaleMax = Math.max(sx, sy) * this._cocosScale;

		this.canvas = cc.find('Canvas');


		// cc.log('cc.Canvas: ', cc.Canvas);
	},

	start() {
		let getData = this.getData.bind(this);
		if (window && window.courseware) {
			getData = window.courseware.getData;
		}
		getData((data) => {
			console.log('data:', data);
			this.data = data || this.getDefaultData();
			console.log('this.data:', this.data);

			this.preloadItem()
		})
	},

	_imageResList: null,
	_audioResList: null,
	_animaResList: null,
	preloadItem() {
		this.addPreloadImage();
		this.addPreloadAudio();
		this.addPreloadAnima();
		this.preload();
	},


	getData(func) {
		if (window && window.courseware) {
			window.courseware.getData(func, 'dfzx_cocos_dqq');
			return;
		}
		
		const middleLayer = cc.find('middleLayer');
		if (middleLayer) {
			const middleLayerComponent = middleLayer.getComponent('middleLayer');
			middleLayerComponent.getData(func);
			return;
		}
		
		func(this.getDefaultData());
	},

	getDefaultData() {
	
		return {"aiClassData":{"time":60,"startTime":0,"itemArr":[{"gId":"0","data":{"name":"镜头","camera":true,"copy":true,"color":"#84f466"},"nickName":"镜头"},{"gId":"2","data":{"name":"龙骨","anima":true,"commonProp":true,"copy":true,"color":"#ffa4e6"},"nickName":"龙骨","skeJsonData":{"url":"http://staging-teach.cdn.ireadabc.com/e3ab840baf83c0b0d571e2420536286f.json","name":"鱼_ske.json"},"texJsonData":{"url":"http://staging-teach.cdn.ireadabc.com/d181f59eb6a4ad6cf124587ca6b34c0e.json","name":"鱼_tex.json"},"texPngData":{"url":"http://staging-teach.cdn.ireadabc.com/f566cca10fd83f62a465b144ac73d483.png","name":"鱼_tex.png"},"keyArrData":[{"panelGroup":[],"time":1,"x":"-0.2"}]},{"gId":"4","data":{"name":"按钮","pic":true,"commonProp":true},"nickName":"按钮","keyArrData":[{"panelGroup":[],"time":2,"x":"0.2"}],"pic_url":"http://staging-teach.cdn.ireadabc.com/790525a2e3b223339c8dfcd6a97361ba.png"},{"gId":"2","data":{"name":"龙骨","anima":true,"commonProp":true,"copy":true,"color":"#ffa4e6"},"nickName":"龙骨","keyArrData":[{"panelGroup":[],"time":2.975,"x":"0.2","y":"-0.2","times":"1"}],"skeJsonData":{"url":"http://staging-teach.cdn.ireadabc.com/bd29690a750530cf6e822f6e418ed1ae.json","name":"小汽车_ske.json"},"texJsonData":{"url":"http://staging-teach.cdn.ireadabc.com/bb18572d3c4bb94f8a9afc8ea726c90d.json","name":"小汽车_tex.json"},"texPngData":{"url":"http://staging-teach.cdn.ireadabc.com/84bce64cd4259e604a458d08ddd75bec.png","name":"小汽车_tex.png"}},{"gId":"1","data":{"name":"图片","pic":true,"fill":true,"commonProp":true,"copy":true,"color":"#ffde00"},"nickName":"图片","keyArrData":[{"panelGroup":[],"time":0.012}],"isFill":true,"pic_url":"http://staging-teach.cdn.ireadabc.com/35f003bb6d0e410494d606fd4055ddb4.png"},{"gId":"5","data":{"name":"重玩按钮","pic":true,"commonProp":true},"nickName":"重玩按钮","keyArrData":[{"panelGroup":[],"time":5,"y":"-0.3"}],"pic_url":"http://staging-teach.cdn.ireadabc.com/3a552c7843003f6803267a03546db24b.png"}]}}
	},

	preload() {
		const preloadArr = this._imageResList.concat(this._audioResList).concat(this._animaResList);
		cc.assetManager.loadAny(preloadArr, null, null, (err, data) => {
			// console.log(' preload data, ', data);


			this.addServerListener();
			// if (window && window["air"]) {
			// 	window["air"].hideAirClassLoading();
			// }
		});
	},

	addServerListener() {

		if (window && window["air"]) {
			// cc.find('Canvas').opacity = 0;
			window.air.onCourseInScreen = (next) => {
				//  cc.find('Canvas').opacity = 255;
				this.loadEnd();
				next();
			}
			window.air.hideAirClassLoading();
		} else {
			this.loadEnd();
		}


		if (window.air) {
			window.air.osmoHandwritingCallback = (data) => {

				if (!data) {
					console.log('data is not exist!!!');
					return;
				}

				console.log('osmoHandwritingCallback data: ', data);

				if (typeof (data) == 'string') {
					console.log('data is string ');
					const dataObj = JSON.parse(data);

					this.photoEnd(dataObj);
					return;
				}

				// 哲学逻辑
				this.photoEnd(data);

			}
		}

	},

	addPreloadImage() {

		const itemArr = this.data.aiClassData.itemArr;
		for (let i=0; i<itemArr.length; i++) {
			const item = itemArr[i];
			this._imageResList.push({ url: item.pic_url || ''});

			const picArr = item.data.picArr
			if (picArr) {
				for (let j=0; j<picArr.length; j++) {
					this._imageResList.push({ url: picArr[j].pic_url || ''});
				}
			}
		}
	
	},

	addPreloadAudio() {

		const itemArr = this.data.aiClassData.itemArr;
		for (let i=0; i<itemArr.length; i++) {
			const item = itemArr[i];
			this._audioResList.push({ url: item.audio_url || ''});

			const audioArr = item.data.audioArr
			if (audioArr) {
				for (let j=0; j<audioArr.length; j++) {
					this._audioResList.push({ url: audioArr[j].audio_url || ''});
				}
			}
		}

	},

	addPreloadAnima() {


		const itemArr = this.data.aiClassData.itemArr;
		for (let i=0; i<itemArr.length; i++) {
			const item = itemArr[i];
			this._animaResList.push({ url: item.skeJsonData?.url || '' });
			this._animaResList.push({ url: item.texJsonData?.url || ''});
			this._animaResList.push({ url: item.texPngData?.url || ''});


			const animaArr = item.data.animaArr
			if (animaArr) {
				for (let j=0; j<animaArr.length; j++) {

					this._animaResList.push({ url: animaArr[j].skeJsonData?.url || '' });
					this._animaResList.push({ url: animaArr[j].texJsonData?.url || ''});
					this._animaResList.push({ url: animaArr[j].texPngData?.url || ''});
				}
			}
		}

		
	},

	loadEnd() {
		
		this.initData();
		this.initView();
		// this.initMusic();
	},

	initMusic() {
		cc.assetManager.loadRemote(this.data.bg_audio_url, (err, clip) => {
			cc.audioEngine.setMusicVolume(0.3);
			const audioID = cc.audioEngine.playMusic(clip, true);
		});
	},

	aiClassLayer: null,
	myActionArr: null,
	recordTestCount: null,
	initData() {
	
		this.recordTestCount = 0;
		this.curAiClassTime = 0;

		this.myActionArr = [];
		this.initAudioEffect();
	},

	

	rightClip: null,
	wrongClip: null,
	bigStarClip: null,
	btnClip: null,
	finishClip: null,
	selectClip: null,
	starCountClip: null,
	initAudioEffect() {
		this.rightClip = cc.find('Canvas/res/audio/right').getComponent(cc.AudioSource).clip;
		this.wrongClip = cc.find('Canvas/res/audio/wrong').getComponent(cc.AudioSource).clip;
		this.bigStarClip = cc.find('Canvas/res/audio/big_star').getComponent(cc.AudioSource).clip;
		this.btnClip = cc.find('Canvas/res/audio/btn').getComponent(cc.AudioSource).clip;
		this.finishClip = cc.find('Canvas/res/audio/finish').getComponent(cc.AudioSource).clip;
		this.selectClip = cc.find('Canvas/res/audio/select').getComponent(cc.AudioSource).clip;
		this.starCountClip = cc.find('Canvas/res/audio/star_count').getComponent(cc.AudioSource).clip;
	},



	initView() {

		this.showMask();

		this.initAiClass();

	
	},

	showMask() {
		return;

		const mask = getSprNode('lianzi');
		mask.anchorY = 0;
		mask.y = -this.canvas.height / 2;

		const sx = this.canvas.width / mask.width;
		const sy = this.canvas.height / mask.height;
		mask.scale = Math.max(sx, sy);
		this.canvas.addChild(mask, 20);
		this.mask = mask;
	},

	hideMask() {
		return;

		if (this.mask) {

			cc.tween(this.mask)
				.to(0.7, {y: this.canvas.height / 2})
				.call(() => {
					this.aiClassStart();
					this.mask.active = false;
				})
				.start();

		
		}
	},

	jumpTargetTime() {

		console.log(" in jumpTargetTime")

		const time = this.data.aiClassData.startTime;
		if (!time) {
			return;
		}
		

		this.curAiClassTime = Number(time);
		const itemArr = this.aiClassItemArr;



		for( let i=0; i<itemArr?.length; i++ ) {
			const keyArrData = itemArr[i].data.keyArrData;
			// console.log('keyArrData.length:', keyArrData.length);
			for( let j=0; j<keyArrData?.length; j++) {
				const keyData = keyArrData[j];
				if (keyData.isStart) {
					continue;
				}

				if (keyData.time <= time) {

					if (itemArr[i].data.gId == 4 || itemArr[i].data.gId == 5) {
	
					} else {
						this.showJumpKeyData(itemArr[i], keyData);

						if (itemArr[i].data.gId == 2) {
							console.log('keyData: ' , JSON.stringify( keyData) );
							console.log('opacity: ' , itemArr[i].opacity)
							console.log('active: ' , itemArr[i].active)
							console.log('i: ' , i)
						}
					}
					keyData.isStart = true;


				} else {
					break;
				}
			}
		}

	},

	aiClassStart() {
		this.isAiClassStart = true;

	},


	initAiClass() {

		this.initAiClassLayer();
		this.initAiClassItemArr();
	},

	initAiClassLayer() {
		this.aiClassLayer = new cc.Node();
		this.aiClassLayer.width = this.canvas.width;
		this.aiClassLayer.height = this.canvas.height;
		this.canvas.addChild(this.aiClassLayer);
	},

	initAiClassItemArr() {

		this.aiClassItemArr = [];

		const promiseArr = [];

		const itemDataArr = this.data.aiClassData.itemArr;
		for( let i=0; i<itemDataArr.length; i++ ) {
			const itemData = itemDataArr[i];
			itemData.itemIndex = i;

			console.log('load itemData: ', JSON.stringify(itemData));
			// console.log(' load item : ', JSON.stringify(item));

			let item;
			switch(itemData.gId.toString()) {

				case '0':
					item = this.getAiCameraItem(itemData);
					break;
				case '1':
					item = this.getAiPicItem(itemData);
					break;
				case '2':
					item = this.getAiAnimaItem(itemData);
					break;
				case '3':
					item = this.getAiAudioItem(itemData);
					break
				case '4':
					item = this.getNormalBtnItem(itemData);
					// item = this.getAiQuestionItem(itemData);
					break
				case '5':
					item = this.getReplayBtnItem(itemData);
					// item = this.getAiSpeechTestItem(itemData);
					break
			}


			promiseArr.push(item);
						
			// if (this.isDestroy) {
			// 	return;
			// }

			// if (itemData.gId != '0') {
			// 	item.active = false;
			// }

			// item.data = itemData;
			// this.aiClassItemArr.push(item);

		}


		Promise.all(promiseArr).then((result) => {
			console.log(result)               //['成功了', 'success']

			this.allItemLoadEnd(result);

		}).catch((error) => {
			console.log(error)
		})
		

		
	},

	allItemLoadEnd(result) {

		console.log(' in allItemLoadEnd: ', result);

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

			const item = result[i];
			if (this.isDestroy) {
				return;
			}
	
			const {itemData} = item;
			if (itemData.gId != '0') {
				item.active = false;
			}
	
			item.data = itemData;
			this.aiClassItemArr.push(item);
		}
		

				
		this.jumpTargetTime();


		this.hideMask();
	},

	getAiCameraItem(itemData) {
		return new Promise((resolve, reject) => {
				const node = this.aiClassLayer;
				node.isCamera = true;
				node.itemData = itemData;
				resolve(node);
		})
	},

	getAiPicItem(itemData) {

		return new Promise((resolve, reject) => {
			
			getSprNodeByUrl(itemData.pic_url, (spr) => {

				if (this.isDestroy) {
					return;
				}

				const sprNode = spr.node;
				let zIndex = 1;
				let scale = this._mapScaleMin;

				if(itemData.isFill == true) {
					zIndex = 0;
					scale = getMaxScale(sprNode, this.canvas.width, this.canvas.height);
				}
	
				sprNode.scale = scale
				sprNode.baseS = sprNode.scale;
				this.aiClassLayer.addChild(sprNode, zIndex + 0.0001 * itemData.itemIndex);

				sprNode.itemData = itemData;
				resolve(sprNode);
			});
		})
	
	},

	getAiAnimaItem(itemData) {


		return new Promise((resolve, reject) => {

			const data = itemData;
			const animaNode = new cc.Node();
			// animaNode.name = 'anima_' + data.index;

			let zIndex = 1;
			this.aiClassLayer.addChild(animaNode, zIndex + 0.0001 * itemData.itemIndex);


			const dragonDisplay = animaNode.addComponent(dragonBones.ArmatureDisplay);
			if (!data.texPngData) {
				return
			}
			
			const image = data.texPngData.url//"http://staging-teach.cdn.ireadabc.com/5a0c5af3e952acd0ac83a6e5c6f03ff1.png";
			const ske = data.skeJsonData.url//"http://staging-teach.cdn.ireadabc.com/bd825dcceea298d1146be8067ae3d17f.json";
			const atlas = data.texJsonData.url//"http://staging-teach.cdn.ireadabc.com/246f8991b729fa3e5a7f4802de828efa.json";
		
		
			cc.loader.load(image, (error, texture) => {

				cc.loader.load({url: atlas, type: 'txt'}, (error, atlasJson) => {

					cc.loader.load({url: ske, type: 'txt'}, (error, dragonBonesJson) => {

						if (this.isDestroy) {
							return;
						}

						const atlas = new dragonBones.DragonBonesAtlasAsset();
						atlas.atlasJson = atlasJson;
						atlas.texture = texture;

						const asset = new dragonBones.DragonBonesAsset();
						asset.dragonBonesJson = dragonBonesJson;

						dragonDisplay.dragonAtlasAsset = atlas;
						dragonDisplay.dragonAsset = asset;

						

						let json = JSON.parse(asset.dragonBonesJson);
						let armatures = json["armature"];
						// console.log('armatures: ', armatures);
						let armatureNames = [];
						for (let i = 0; i < armatures.length; i++) {
							armatureNames.push(armatures[i].name);
						}
						// console.log('armatureNames: ', armatureNames);
						if (armatureNames.length > 0) {
							let defaultArmatureName = armatureNames[0];
							dragonDisplay.armatureName = defaultArmatureName;
							// let animationNames = dragonDisplay.getAnimationNames(defaultArmatureName);
							let defaultArmature = armatures[0];
							let animations = defaultArmature.animation;
							let animationNames = [];
							for (let i = 0; i < animations.length; i++) {
								animationNames.push(animations[i].name);
							}

							animaNode.animationNames = animationNames;

						}

						animaNode.scale = this._mapScaleMin;
						animaNode.baseS = animaNode.scale;
						animaNode.itemData = itemData;
						resolve(animaNode);
					});
				});
			});


		})

		
	},



	getAiAudioItem(itemData) {

		console.log( ' in getAiAudioItem: ', itemData);

		return new Promise((resolve, reject) => {
			this.getAudioClipByUrl(itemData.audio_url, (clip) => {

				if (this.isDestroy) {
					return;
				}

				console.log( ' in getAudioClipByUrl end: ', clip);

				if (clip) {
					const audioNode = new cc.Node();
					const as = audioNode.addComponent(cc.AudioSource);
					as.clip = clip;
					audioNode.itemData = itemData;
					resolve(audioNode);
				} else {
					reject();
				}
		
			})
		})

	},

	getReplayBtnItem(itemData) {
		return new Promise((resolve, reject) => {
			
			getSprNodeByUrl(itemData.pic_url, (spr) => {

				if (this.isDestroy) {
					return;
				}

				const sprNode = spr.node;
				let zIndex = 1;
				let scale = this._mapScaleMin;
	
				sprNode.scale = scale
				sprNode.baseS = sprNode.scale;
				this.aiClassLayer.addChild(sprNode, zIndex + 0.0001 * itemData.itemIndex);

				sprNode.itemData = itemData;

				sprNode.on('touchstart', () => {
					this.normalBtnClick(sprNode);
				})


				resolve(sprNode);
			});
		})
	},

	getNormalBtnItem(itemData) {
		return new Promise((resolve, reject) => {
			
			getSprNodeByUrl(itemData.pic_url, (spr) => {

				if (this.isDestroy) {
					return;
				}

				const sprNode = spr.node;
				let zIndex = 1;
				let scale = this._mapScaleMin;
	
				sprNode.scale = scale
				sprNode.baseS = sprNode.scale;
				this.aiClassLayer.addChild(sprNode, zIndex + 0.0001 * itemData.itemIndex);

				sprNode.itemData = itemData;

				sprNode.on('touchstart', () => {
					this.normalBtnClick(sprNode);
				})


				resolve(sprNode);
			});
		})
	},

	getAiSpeechTestItem(itemData) {
		return new Promise((resolve, reject) => {
			
			const baseLayer = new cc.Node();
			// this.aiClassLayer.addChild(questionLayer);

		
			let picNodeArr = [];
			let animaNodeArr = [];
			let audioNodeArr = [];
			const checkLayerFinish = () => {
				if (this.isDestroy) {
					this.reject();
				}

				if (itemData.data.picArr && picNodeArr.length != itemData.data.picArr.length) {
					return;
				}
				if (itemData.data.animaArr && animaNodeArr.length != itemData.data.animaArr.length) {
					return;
				}
				if (itemData.data.audioArr && audioNodeArr.length != itemData.data.audioArr.length) {
					return;
				}
				
				picNodeArr.sort((a, b) => {
					return a.index - b.index;
				})
				animaNodeArr.sort((a, b) => {
					return a.index - b.index;
				})
				audioNodeArr.sort((a, b) => {
					return a.index - b.index;
				})

				baseLayer.picNodeArr = picNodeArr;
				baseLayer.animaNodeArr = animaNodeArr;
				baseLayer.audioNodeArr = audioNodeArr;
				baseLayer.itemData = itemData;



				resolve(baseLayer);

			}

			console.log('itemData: ', itemData);
			const picDataArr = itemData.data.picArr || [];
			for (let i=0; i<picDataArr.length; i++) {
				this.getOneAiPic(picDataArr[i].pic_url, false, (sprNode)=> {
					sprNode.index = i;
					sprNode.active = false;

					this.aiClassLayer.addChild(sprNode, sprNode.zIndex + 0.0001 * itemData.itemIndex);
					picNodeArr.push(sprNode);
					checkLayerFinish();
				})
			}

			const animaArr = itemData.data.animaArr || [];
			for (let i=0; i<animaArr.length; i++) {
				this.getOneAiAnima(animaArr[i], (animaNode)=> {
					animaNode.index = i;
					animaNode.active = false;
					let zIndex = i;
					this.aiClassLayer.addChild(animaNode, zIndex + 0.0001 * itemData.itemIndex);
					animaNodeArr.push(animaNode);
					checkLayerFinish();
				})
			}

			const audioArr = itemData.data.audioArr || [];
			for (let i=0; i<audioArr.length; i++) {
				this.getOneAiAudio(audioArr[i].audio_url, (audioNode)=> {
					audioNode.index = i;
					audioNode.active = false;
					audioNodeArr.push(audioNode);
					checkLayerFinish();
				})
			}

		})
	},

	getAiQuestionItem(itemData) {

		return new Promise((resolve, reject) => {
			
			const questionLayer = new cc.Node();
			// this.aiClassLayer.addChild(questionLayer);

			let picNodeArr = [];
			let animaNodeArr = [];
			let audioNodeArr = [];
			const checkLayerFinish = () => {
				if (this.isDestroy) {
					reject();
				}

				if (picNodeArr.length != itemData.data.picArr.length) {
					return;
				}
				if (animaNodeArr.length != itemData.data.animaArr.length) {
					return;
				}
				if (audioNodeArr.length != itemData.data.audioArr.length) {
					return;
				}
				
				picNodeArr.sort((a, b) => {
					return a.index - b.index;
				})
				animaNodeArr.sort((a, b) => {
					return a.index - b.index;
				})
				audioNodeArr.sort((a, b) => {
					return a.index - b.index;
				})

				questionLayer.picNodeArr = picNodeArr;
				questionLayer.animaNodeArr = animaNodeArr;
				questionLayer.audioNodeArr = audioNodeArr;
				questionLayer.itemData = itemData;

				resolve(questionLayer);

			}

			console.log('itemData: ', itemData);
			const picDataArr = itemData.data.picArr;
			for (let i=0; i<picDataArr.length; i++) {
				this.getOneAiPic(picDataArr[i].pic_url, false, (sprNode)=> {
					sprNode.index = i;
					sprNode.active = false;
					this.aiClassLayer.addChild(sprNode, sprNode.zIndex + 0.0001 * itemData.itemIndex);
					picNodeArr.push(sprNode);
					checkLayerFinish();
				})
			}

			const animaArr = itemData.data.animaArr;
			for (let i=0; i<animaArr.length; i++) {
				this.getOneAiAnima(animaArr[i], (animaNode)=> {
					animaNode.index = i;
					animaNode.active = false;
					let zIndex = i;
					this.aiClassLayer.addChild(animaNode, zIndex + 0.0001 * itemData.itemIndex);
					animaNodeArr.push(animaNode);
					checkLayerFinish();
				})
			}

			const audioArr = itemData.data.audioArr;
			for (let i=0; i<audioArr.length; i++) {
				this.getOneAiAudio(audioArr[i].audio_url, (audioNode)=> {
					audioNode.index = i;
					audioNode.active = false;
					audioNodeArr.push(audioNode);
					checkLayerFinish();
				})
			}

		})
	},

	getOneAiPic(pic_url, isFill, cb) {

		if (!pic_url) {
			cb(new cc.Node());
			return;
		}
		getSprNodeByUrl(pic_url, (spr) => {

			if (this.isDestroy) {
				return;
			}

			const sprNode = spr.node;
			let zIndex = 1;
			let scale = this._mapScaleMin;

			if(isFill == true) {
				zIndex = 0;
				scale = getMaxScale(sprNode, this.canvas.width, this.canvas.height);
			}
				
			sprNode.scale = scale
			sprNode.baseS = sprNode.scale;
			sprNode.zIndex = zIndex;

			cb(sprNode);
		});
	},

	getOneAiAnima(data, cb) {

		if (!data?.texPngData?.url || !data?.skeJsonData?.url || !data?.texJsonData?.url) {
			 cb(new cc.Node())
			 return;
		}

		const animaNode = new cc.Node();
		// this.aiClassLayer.addChild(animaNode);


		const dragonDisplay = animaNode.addComponent(dragonBones.ArmatureDisplay);
		
		const image = data.texPngData.url//"http://staging-teach.cdn.ireadabc.com/5a0c5af3e952acd0ac83a6e5c6f03ff1.png";
		const ske = data.skeJsonData.url//"http://staging-teach.cdn.ireadabc.com/bd825dcceea298d1146be8067ae3d17f.json";
		const atlas = data.texJsonData.url//"http://staging-teach.cdn.ireadabc.com/246f8991b729fa3e5a7f4802de828efa.json";
	
	
		cc.loader.load(image, (error, texture) => {

			cc.loader.load({url: atlas, type: 'txt'}, (error, atlasJson) => {

				cc.loader.load({url: ske, type: 'txt'}, (error, dragonBonesJson) => {

					if (this.isDestroy) {
						return;
					}

					const atlas = new dragonBones.DragonBonesAtlasAsset();
					atlas.atlasJson = atlasJson;
					atlas.texture = texture;

					const asset = new dragonBones.DragonBonesAsset();
					asset.dragonBonesJson = dragonBonesJson;

					dragonDisplay.dragonAtlasAsset = atlas;
					dragonDisplay.dragonAsset = asset;

					

					let json = JSON.parse(asset.dragonBonesJson);
					let armatures = json["armature"];
					// console.log('armatures: ', armatures);
					let armatureNames = [];
					for (let i = 0; i < armatures.length; i++) {
						armatureNames.push(armatures[i].name);
					}
					// console.log('armatureNames: ', armatureNames);
					if (armatureNames.length > 0) {
						let defaultArmatureName = armatureNames[0];
						dragonDisplay.armatureName = defaultArmatureName;
						// let animationNames = dragonDisplay.getAnimationNames(defaultArmatureName);
						let defaultArmature = armatures[0];
						let animations = defaultArmature.animation;
						let animationNames = [];
						for (let i = 0; i < animations.length; i++) {
							animationNames.push(animations[i].name);
						}

						animaNode.animationNames = animationNames;

					}

					animaNode.scale = this._mapScaleMin;
					animaNode.baseS = animaNode.scale;
					cb(animaNode);
				});
			});
		});

	},

	getOneAiAudio(audio_url, cb) {

		console.log(' in getOneAiAudio:', audio_url);

		if (!audio_url) {
			cb(new cc.Node());
			return;
		}

		this.getAudioClipByUrl(audio_url, (clip) => {
			if (this.isDestroy) {
				return;
			}

			if (clip) {
				const audioNode = new cc.Node();
				const as = audioNode.addComponent(cc.AudioSource);
				as.clip = clip;
				cb(audioNode);
			} else {
				cb();
			}
	
		})


	},
	
	normalBtnClick(sprNode) {
		const {itemData} = sprNode;


	},

	getAudioClipByUrl(audio_url, cb) {
		if (audio_url) {
			cc.assetManager.loadRemote(audio_url, (err, audioClip) => {
				cb(audioClip);
			});
		} else {
			cb();
		}
	},


	showItemKeyData(item, keyData) {
		console.log('in showItemKeyData');

		switch(item.data.gId.toString()) {
			case '0':
				this.showCameraKeyData(item, keyData);
				break;

			case '1':
				this.showPicKeyData(item, keyData);
				break;

			case '2':
				this.showAnimaKeyData(item, keyData);
				break;

			case '3':
				this.showAudioKeyData(item, keyData);
				break;

			case '4':
				this.showNormalBtnKeyData(item, keyData);
				// this.showQuestionKeyData(item, keyData);
				break;

			// case '5':
			// 	this.showSpeechTestKeyData(item, keyData);
			// 	break;
		}

	
	},

	getItemPropertyAiClass(item, key) {

		let tempNum = 1;
		if (item.isCamera) {
			tempNum = -1;
		}

		switch(key) {
			case 'x':
				return item[key] / this.canvas.width * tempNum;
			case 'y':
				return item[key] / this.canvas.height * tempNum;
			case 'scaleX':
			case 'scaleY':
				return item[key] / (item.baseS || 1);
		}
		return item[key];
	},

	setItemPropertyAiClass(item, key, data) {

		let tempNum = 1;
		if (item.isCamera) {
			tempNum = -1;
		}

		switch(key) {
			case "x":
				data *= this.canvas.width * tempNum;
				break;
			case "y":
				data *= this.canvas.height * tempNum;
				break;
			case 'scaleX':
			case 'scaleY':
				data *= (item.baseS || 1);
				break;
			case 'active':
				data = JSON.parse(data);
			// case 'zIndex':
			// 	data += 10.0001 * item.itemIndex;
		}

		item[key] = data;

	},

	showJumpKeyData(item, keyData) {


		for( let key in keyData ) {
			if (item[key] != null && keyData[key] != null && keyData[key] != '') {
				this.setItemPropertyAiClass(item, key, keyData[key])
			}
		}

		if (item.opacity > 0) {
			item.active = true;
		} else {
			item.active = false;
		}


	},

	showCameraKeyData(item, keyData) {

		console.log(' in showCameraKeyData');

		if (item.curKeyActionArr) {
			this.cleanCurKeyActionArr(item);
		}

		for( let key in keyData ) {
			if (item[key] != null && keyData[key] != null && keyData[key] != '') {
				this.setItemPropertyAiClass(item, key, keyData[key])
			}
		}

		const actionArr = [];
		const keyArrData = item.data.keyArrData;
		const index = keyArrData.indexOf(keyData);
		const nextKeyData = keyArrData[index + 1];
		if (nextKeyData) {
			// 动作变化
			for( let key in keyData ) {
				if (item[key] != null && nextKeyData[key] && (nextKeyData[key] != keyData[key])) {
				
					const changeTime = nextKeyData.time - keyData.time;

					const changeData = {};
					changeData[key] = nextKeyData[key];

					const action = this.addMyAction(item, changeTime, changeData);
					actionArr.push(action);
				}
			}


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

			item.curKeyActionArr = actionArr;
		}

	},

	showPicKeyData(item, keyData) {

		if (item.curKeyActionArr) {
			this.cleanCurKeyActionArr(item);
		}

		for( let key in keyData ) {
			if (item[key] != null && keyData[key] != null && keyData[key] != '') {
				this.setItemPropertyAiClass(item, key, keyData[key])
			}
		}

		if (item.opacity > 0) {
			item.active = true;
		} else {
			item.active = false;
		}

		
		const actionArr = [];
		const keyArrData = item.data.keyArrData;
		const index = keyArrData.indexOf(keyData);
		const nextKeyData = keyArrData[index + 1];
		if (nextKeyData) {
			// 动作变化
			for( let key in keyData ) {
				if (item[key] != null && nextKeyData[key] && (nextKeyData[key] != keyData[key])) {
				
					const changeTime = nextKeyData.time - keyData.time;

					const changeData = {};
					changeData[key] = nextKeyData[key];

					const action = this.addMyAction(item, changeTime, changeData);
					actionArr.push(action);
				}
			}

			item.curKeyActionArr = actionArr;
		}

	},

	showAnimaKeyData(item, keyData) {

		if (item.curKeyActionArr) {
			this.cleanCurKeyActionArr(item);
		}

		let animation = item.animationNames[0];
		let times = -1;
		for( let key in keyData ) {
			if (item[key] != null && keyData[key] != null && keyData[key] != '') {
				
				this.setItemPropertyAiClass(item, key, keyData[key])
			} else {

				switch(key) {
					case 'animation':
						animation = keyData[key];
						break;
					case 'times':
						times = keyData[key];
						break;
				}

			}
		}

		if (item.opacity > 0) {
			item.active = true;
		} else {
			item.active = false;
		}

		const keyArrData = item.data.keyArrData;
		const index = keyArrData.indexOf(keyData);
		const nextKeyData = keyArrData[index + 1];
		const actionArr = [];
		if (nextKeyData) {
			// 动作变化
			for( let key in keyData ) {
				if (item[key] != null && nextKeyData[key] && keyData[key] != null && keyData[key] != '' && (nextKeyData[key] != keyData[key])) {
				
					const changeTime = nextKeyData.time - keyData.time;

					const changeData = {};
					changeData[key] = nextKeyData[key];

					const action = this.addMyAction(item, changeTime, changeData);
					actionArr.push(action);
				}
			}

			item.curKeyActionArr = actionArr;
		}

		const dragonDisplay = item.getComponent(dragonBones.ArmatureDisplay);
		dragonDisplay.playAnimation(animation, Number(times));

		console.log(' anima _ name: ', animation);
		console.log(' anima _ times: ', times);

	},



	showAudioKeyData(item, keyData) {
		console.log(' in showAudioKeyData item', item);
		console.log(' in showAudioKeyData keyData ', keyData);

		const as = item.getComponent(cc.AudioSource);
		const times = keyData.times || 1;
		let curTimes = 0

		const playAudioKey = () => {
			playAudio(as.clip, () => {
				curTimes ++ ;
				if (times <= 0 || curTimes < times) {
					playAudioKey();
				}
			})
		}

		playAudioKey();
	},

	showQuestionKeyData(item, keyData) {
		
		console.log('~~item: ', item);
		console.log('~~keyData: ', keyData);

		const {panelGroup} = keyData;

		for(let i=0; i<5; i++) {
			const groupData = panelGroup[i].data;
			const groupItem = item.picNodeArr[i];
			for( let key in groupData ) {
				if (groupItem[key] != null && groupData[key] != null && groupData[key] != '') {	
					this.setItemPropertyAiClass(groupItem, key, groupData[key])

					switch(i) {
						case 1:
							groupItem.lightSpr = item.picNodeArr[5];
							this.setItemPropertyAiClass(groupItem.lightSpr, key, groupData[key])
							break;
						case 2:
							groupItem.lightSpr = item.picNodeArr[6];
							this.setItemPropertyAiClass(groupItem.lightSpr, key, groupData[key])
							break;
					}
				}
			}

			if (groupItem.opacity > 0) {
				groupItem.active = true;
			} else {
				groupItem.active = false;
			}
		}

		console.log('~panelGroup: ', panelGroup);
		console.log('~item.animaNodeArr: ', item.animaNodeArr);

		const animaStartIndex = 5;
		for(let i=animaStartIndex; i<panelGroup.length; i++) {
			const groupData = panelGroup[i].data;
			const groupItem = item.animaNodeArr[i - animaStartIndex];

			let animation = groupItem.animationNames && groupItem.animationNames[0];
			let times = -1;

			for( let key in groupData ) {
				if (groupItem[key] != null && groupData[key] != null && groupData[key] != '') {	
					this.setItemPropertyAiClass(groupItem, key, groupData[key])
				} else {
					
					switch(key) {
						case 'animation':
							animation = keyData[key];
							break;
						case 'times':
							times = keyData[key];
							break;
					}
				}

			}

			groupItem.curAnimation = animation;
			if (i == panelGroup.length - 1) {
				groupItem.active = true;
				this.normalAnima = groupItem;

				const dragonDisplay = groupItem.getComponent(dragonBones.ArmatureDisplay);
				if (dragonDisplay) {
					dragonDisplay.playAnimation(animation, Number(times));
				}
			}
		}


		const replayBtn = item.picNodeArr[4];
		replayBtn.active = false;
		this.replayBtn = replayBtn;


		if (keyData.appearTime) {

			this.showAppearAnima(item, keyData, () => {
				this.showQuestionKeyDataStart(item, keyData);
			});
			
		} else {
			this.showQuestionKeyDataStart(item, keyData);
		}
	},

	showSpeechTestKeyData(item, keyData) {
		
		console.log('in showSpeechTestKeyData item: ', item);
		console.log('keyData: ', keyData);

		const {panelGroup} = keyData;

		// for(let i=0; i<5; i++) {
		// 	const groupData = panelGroup[i].data;
		// 	const groupItem = item.picNodeArr[i];
		// 	for( let key in groupData ) {
		// 		if (groupItem[key] != null && groupData[key] != null && groupData[key] != '') {	
		// 			this.setItemPropertyAiClass(groupItem, key, groupData[key])

		// 			switch(i) {
		// 				case 1:
		// 					groupItem.lightSpr = item.picNodeArr[5];
		// 					this.setItemPropertyAiClass(groupItem.lightSpr, key, groupData[key])
		// 					break;
		// 				case 2:
		// 					groupItem.lightSpr = item.picNodeArr[6];
		// 					this.setItemPropertyAiClass(groupItem.lightSpr, key, groupData[key])
		// 					break;
		// 			}
		// 		}
		// 	}

		// 	if (groupItem.opacity > 0) {
		// 		groupItem.active = true;
		// 	} else {
		// 		groupItem.active = false;
		// 	}
		// }

		console.log('~panelGroup: ', panelGroup);
		console.log('~item.animaNodeArr: ', item.animaNodeArr);

		const animaStartIndex = 0;
		for(let i=animaStartIndex; i<panelGroup.length; i++) {
			const groupData = panelGroup[i].data;
			const groupItem = item.animaNodeArr[i - animaStartIndex];

			let animation = groupItem.animationNames && groupItem.animationNames[0];
			let times = -1;

			for( let key in groupData ) {
				if (groupItem[key] != null && groupData[key] != null && groupData[key] != '') {	
					this.setItemPropertyAiClass(groupItem, key, groupData[key])
				} else {
					
					switch(key) {
						case 'animation':
							animation = keyData[key];
							break;
						case 'times':
							times = keyData[key];
							break;
					}
				}

			}

			groupItem.curAnimation = animation;
			if (i == panelGroup.length - 1) {
				groupItem.active = true;
				this.normalAnima = groupItem;

				const dragonDisplay = groupItem.getComponent(dragonBones.ArmatureDisplay);
				if (dragonDisplay) {
					dragonDisplay.playAnimation(animation, Number(times));
				}
			}
		}


		// const replayBtn = item.picNodeArr[4];
		// replayBtn.active = false;
		// this.replayBtn = replayBtn;


		// if (keyData.appearTime) {

		// 	this.showAppearAnima(item, keyData, () => {
		// 		this.showSpeechTestKeyDataStart(item, keyData);
		// 	});
			
		// } else {
			this.showSpeechTestKeyDataStart(item);
		// }
	},
	
	showNormalBtnKeyData(item, keyData) {
		if (item.curKeyActionArr) {
			this.cleanCurKeyActionArr(item);
		}

		for( let key in keyData ) {
			if (item[key] != null && keyData[key] != null && keyData[key] != '') {
				this.setItemPropertyAiClass(item, key, keyData[key])
			}
		}

		// if (item.opacity > 0) {
		// 	item.active = true;
		// } else {
		// 	item.active = false;
		// }

		
		// const actionArr = [];
		// const keyArrData = item.data.keyArrData;
		// const index = keyArrData.indexOf(keyData);
		// const nextKeyData = keyArrData[index + 1];
		// if (nextKeyData) {
		// 	// 动作变化
		// 	for( let key in keyData ) {
		// 		if (item[key] != null && nextKeyData[key] && (nextKeyData[key] != keyData[key])) {
				
		// 			const changeTime = nextKeyData.time - keyData.time;

		// 			const changeData = {};
		// 			changeData[key] = nextKeyData[key];

		// 			const action = this.addMyAction(item, changeTime, changeData);
		// 			actionArr.push(action);
		// 		}
		// 	}

		// 	item.curKeyActionArr = actionArr;
		// }
	},

	showSpeechTestKeyDataStart(item) {
		this.isAiClassStart = false;
		
		console.log('item.data~~: ', item.data)
		const text = item.data.data.labelArr[0].value;
		this.startRecord(text, item);
	},

	startRecord(text, item) {
		console.log(' in startRecord .. text: ', text);

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

		const time = Number(item.data.data.labelArr[1].value) || 4;
		const spellingLetter = item.data.data.labelArr[2]?.value;

		if (window.courseware) {

			//开始录音
			if (spellingLetter) {

				console.log('~letter: ', spellingLetter);
				window.courseware.startTest(text, {"pronounce": spellingLetter}); 
			} else {
				window.courseware.startTest(text); 
			}
		}
		this._timeoutIds.push( setTimeout(() => {
			if (!window.courseware) return this.recrodEnd({
				"dtLastResponse": "2021-09-17 13:36:26:109",
				"refText": "I haven't found anything out about him yet.",
				"recordId": "6144295213f0a2200000ed93",
				"eof": 1,
				"result": {
					"pronunciation": 75,
					"resource_version": "3.1.0",
					"fluency": 60,
					"rhythm": 90,
					"kernel_version": "5.2.4",
					"overall": 74,
					"integrity": 100,
					"duration": "6.779",
					"rear_tone": "fall",
					"speed": 96,
				},
				"tokenId": "6144295408558b08dd000001",
				"applicationId": "154838659000009e"
			}, item)

			console.log(' record 11 ')

			window.courseware && window.courseware.stopTest((data) => {
				console.log(' record 22 ', data);
				data = JSON.parse(data);
				this.recrodEnd(data, item);
			}); //结束录音
		}, time * 1000));

	},

	recrodEnd(data, item) {

		console.log('record end');
		let score = data.result.overall;

		this.recordTestCount ++;
		if (this.recordTestCount >= 2) {

			console.log(' panelGroupShowEnd 2 ')
			this.panelGroupShowEnd(item);
			return;
		}

		if (score >= 80) {
			this.showAnimaRight(item, () => {
			});
			this.showPanelGroupAudio(item, 0, () => {

				console.log(' panelGroupShowEnd 1 ')
				this.panelGroupShowEnd(item);
			});

		} else {

			this.showAnimaWrong(item, () => {
			});
			this.showPanelGroupAudio(item, 1, () => {

				this.showAnimaNormal(item);
				this.showSpeechTestKeyDataStart(item);

			});
		}
	},

	showAppearAnima(item, keyData, callback) {
		const appearAnim = (node, time, cb) => {
			node.opacity = 0;
			cc.tween(node)
				.to(time, {opacity: 255})
				.call(() => {
					cb()
				})
				.start()
		}
		
		const picNodeArr = item.picNodeArr;
		for (let i=0; i<4; i++) {
			appearAnim(picNodeArr[i], keyData.appearTime, () => {
				if (i == 0) {
					callback && callback();
					// this.showQuestionKeyDataStart(item, keyData);
				}
			})
		}
	},

	showDisappearAnima(item, keyData) {
		const appearAnim = (node, time, cb) => {
			node.opacity = 255;
			cc.tween(node)
				.to(time, {opacity: 0})
				.call(() => {
					cb()
				})
				.start()
		}
		
		const picNodeArr = item.picNodeArr;
		for (let i=0; i<picNodeArr.length; i++) {
			appearAnim(picNodeArr[i], keyData.disappearTime, () => {
				if (i == 0) {
					this.showQuestionKeyDataStart(item, keyData);
				}
			})
		}
	},



	showQuestionKeyDataStart(item, keyData) {

		this.isAiClassStart = false;
		
		const option1 = item.picNodeArr[1];
		const option2 = item.picNodeArr[2];
		const commit = item.picNodeArr[3];
		const replay = item.picNodeArr[4];
		const option1Light = item.picNodeArr[5];
		const option2Light = item.picNodeArr[6];
		
		const hideOptionLight = () => {
			option1Light.active = false;
			option2Light.active = false;
			option1.active = true;
			option2.active = true;
		}
	
		let selectedId = -1;

		option1.on('touchstart', () => {
			console.log('option1 click')
			if (selectedId == 0) {
				return;
			}
			hideOptionLight();
			option1Light.active = true;
			option1.active = false;
			selectedId = 0;

			this.showPanelGroupAudio(item, 0);
		})

		option2.on('touchstart', () => {

			if (selectedId == 1) {
				return;
			}
			hideOptionLight();
			option2Light.active = true;
			option2.active = false;
			selectedId = 1;
			this.showPanelGroupAudio(item, 1);
		})
	
		commit.on('touchstart', () => {
			console.log('commit click')
			if (selectedId == -1) {
				return;
			}

			this.commitQuestion(selectedId, item, keyData);
			this.showDisappearAnima(item, keyData);
		})

		replay.on('touchstart', () => {
			console.log('replay click')
		})

		option1Light.on('touchstart', () => {
			// console.log('option1Light click')
			// option1.active = true;
			// option1Light.active = false;
		})

		option2Light.on('touchstart', () => {
			// console.log('option2Light click')
			// option2.active = true;
			// option2Light.active = false;
		})
	},


	hideQuestion(item) {
		const picNodeArr = item.picNodeArr;
	},


	commitQuestion(id, item, keyData) {


		console.log(' in commit question :', item.data);
		const option = item.data.data.checkBox.option[id]

		let isAnimaEnd = false;
		let isAudioEnd = false;
		const timeContinue = () => {
			// if (isAnimaEnd && isAudioEnd) {
				this.panelGroupShowEnd();
			// }
		}

		console.log('提交答案： ' , id)


		if (option.isRight) {
			// this.showQuestionRight(item);

			this.showAnimaRight(item, () => {
	
			});
			this.showPanelGroupAudio(item, 2, () => {
				isAudioEnd = true;
				timeContinue();
			});

			this.showCorrectParticle();
	
		} else {
			// this.showQuestionWrong(item);

			this.showAnimaWrong(item, () => {
		
			});
			this.showPanelGroupAudio(item, 3, () => {
				isAudioEnd = true;
				timeContinue();
			});

		}
	},

	showCorrectParticle() {

		const correctNode = cc.find("Canvas/res/anim/correct");
		const pNode = cc.instantiate(correctNode);
		this.canvas.addChild(pNode, 5);

		const dragonDisplay = pNode.getComponent(dragonBones.ArmatureDisplay);
		dragonDisplay.playAnimation('newAnimation', 1);

	},

	panelGroupShowEnd(item) {

		this.isAiClassStart = true;

		this.hideAiPanelGroup(item);
	},

	hideAiPanelGroup(item) {
		const animaNodeArr = item.animaNodeArr;
		for (let i=0; i<animaNodeArr.length; i++) {
			animaNodeArr[i].active = false;
		}
	},


	showPanelGroupAudio(item, index, cb=null) {
		const audioNodeArr = item.audioNodeArr;
		const clip = audioNodeArr[index].getComponent(cc.AudioSource).clip;
		playAudio(clip, () => {
			cb && cb()
		})
	},

	showQuestionRight(item) {
		this.showAnimaRight(item);


	},

	showQuestionWrong(item) {
		this.showAnimaWrong(item);
	},


	showAnimaRight(item) {
		this.normalAnima.active = false;

		const rightAnimaNode = item.animaNodeArr[0];
		rightAnimaNode.active = true;

		const dragonDisplay = rightAnimaNode.getComponent(dragonBones.ArmatureDisplay)
		dragonDisplay.playAnimation(rightAnimaNode.curAnimation, -1);

	},

	showAnimaWrong(item) {
		this.normalAnima.active = false;

		const wrongAnimaNode = item.animaNodeArr[1];
		wrongAnimaNode.active = true;

		const dragonDisplay = wrongAnimaNode.getComponent(dragonBones.ArmatureDisplay)
		dragonDisplay.playAnimation(wrongAnimaNode.curAnimation, -1);

		// this.replayBtn.active = true;
	},

	showAnimaNormal(item) {
		this.normalAnima.active = true;

		item.animaNodeArr[0].active = false;
		item.animaNodeArr[1].active = false;

		// const dragonDisplay = this.normalAnima.getComponent(dragonBones.ArmatureDisplay);
		// if (dragonDisplay) {
		// 	dragonDisplay.playAnimation(this.normalAnima.curAnimation, -1);
		// }

		// const dragonDisplay = wrongAnimaNode.getComponent(dragonBones.ArmatureDisplay)
		// dragonDisplay.playAnimation(wrongAnimaNode.curAnimation, -1);
	},



	cleanCurKeyActionArr(item) {
		const actionArr = item.curKeyActionArr;
		for (let i=0; i<actionArr.length; i++) {
			removeFromArr(this.myActionArr, actionArr[i]);
		}
	},

	addMyAction(item, changeTime, changeData) {

		const frameChangeData = {};
		for (let key in changeData) {

			const itemProp = this.getItemPropertyAiClass(item, key)

			if (itemProp != null) {
				const totalChangeNum = changeData[key] - itemProp;
				frameChangeData[key] = totalChangeNum / changeTime;
			}
		}

		const actionData = {item, changeTime, changeData, frameChangeData, curChangeTime: 0}
		this.myActionArr.push(actionData);
		
		return actionData;
	},

	finishMyAction(myAction) {
		const {item, changeData} = myAction;
		for (let key in changeData) {
			this.setItemPropertyAiClass(item, key, changeData[key]);
		}

		removeFromArr(this.myActionArr, myAction);
	},


	checkAiClassItemStart() {
		const itemArr = this.aiClassItemArr;

		const needShowKeyDataArr = [];
		let curQuestionData = {};

		for( let i=0; i<itemArr?.length; i++ ) {
			const keyArrData = itemArr[i].data.keyArrData;
			// console.log('keyArrData.length:', keyArrData.length);
			for( let j=0; j<keyArrData?.length; j++) {
				const keyData = keyArrData[j];
				if (keyData.isStart) {
					continue;
				}

				if (keyData.time <= this.curAiClassTime) {

					if (itemArr[i].data.gId == 4 || itemArr[i].data.gId == 5) {
						curQuestionData.item = itemArr[i];
						curQuestionData.keyData = keyData;
						// this.showItemKeyData(itemArr[i], keyData);
						// keyData.isStart = true;
						// return;
					} else {
						needShowKeyDataArr.push([itemArr[i], keyData]);
					}

			
					break;
				}
			}
		}


		let realTime = this.curAiClassTime;
		if (curQuestionData.keyData) {
			const {item, keyData} = curQuestionData;
			realTime = keyData.time;

			this.showItemKeyData(item, keyData);
			keyData.isStart = true;
		}

		for (let i=0; i<needShowKeyDataArr.length; i++) {
			const item = needShowKeyDataArr[i][0];
			const keyData = needShowKeyDataArr[i][1];
			if (keyData.time <= realTime) {
				this.showItemKeyData(item, keyData);
				keyData.isStart = true;
			}
		}
	},

	updateAiClass(dt) {
		if (!this.isAiClassStart) {
			return;
		}

		this.curAiClassTime += dt;
		this.checkAiClassItemStart();
	},

	updateMyAction(dt) {
		const arr = this.myActionArr;
		for (let i=0; i<arr?.length; i++) {
			const {item, changeTime, changeData, frameChangeData} = arr[i];
			for (let key in frameChangeData) {

				const itemProp = this.getItemPropertyAiClass(item, key);
				itemProp += frameChangeData[key] * dt ;
				this.setItemPropertyAiClass(item, key, itemProp);
			}

			arr[i].curChangeTime += dt;
			if (arr[i].curChangeTime >= changeTime) {
				this.finishMyAction(arr[i]);
			}
		}
	},

	update(dt) {

		if (this.isDestroy) {
			return;
		}
		
		this.updateAiClass(dt);
		this.updateMyAction(dt);
	},









	getLabel(text) {
		const labelNode = new cc.Node();
		const label = labelNode.addComponent(cc.Label);
		label.string = text;
		labelNode.color = cc.Color.BLACK;
		label.fontSize = 20;
		return labelNode;
	},










	showTryAgain() {
		const time = 0.3;
		cc.tween(this.tryagain)
			.to(time, {opacity: 255}, {easing: "cubicOut"})
			.delay(0.3)
			.to(time, {opacity: 0}, {easing: "cubicIn"})
			.start();
	},



	gameEnd() {
		console.log('game end !')

		this.isGameEnd = true;

		this.showRestart();
		this.showGoodjob();
		// this.showOneFirework(cc.v2(0, -this.canvas.height / 2), this.canvas, cc.find('paperBase').children, this.canvas.width / 2.5, this.canvas.height * 2, 100, 1);
		playAudio(this.finishClip);


		const camera = cc.find('Canvas/Main Camera');
		camera.zIndex = 100;

		showTrebleFirework(camera, cc.find('RibbonNodeBase').children);

		onHomeworkFinish();

		this.endTesting();
	},

	showGoodjob() {

		const icon = getSprNode("goodjob");
		icon.scale = this._mapScaleMin;
		icon.baseS = icon.scale;
		this.canvas.addChild(icon, 20);


		const time = 1;
		icon.scale = 0;
		cc.tween(icon)
			.to(0.8,  {scale: icon.baseS}, {easing: "elasticOut"})
			.delay(1)
			.to(0.5, {scale: 0} , {easing: "cubicIn"})

			.start();



	},

	showRestart() {

		const btn = getSprNode("btn_restart");
		btn.scale = this._mapScaleMin;
		btn.baseS = btn.scale;
		this.canvas.addChild(btn, 21);

		btn.on(cc.Node.EventType.TOUCH_START, () => {
			// btn.removeFromParent();
			// this.initData();
			// this.initStar();
			// this.showChangeQuesAnim();
			// playAudio(this.btnClip);

			const middleLayer = cc.find('middleLayer');
			if (middleLayer) {
				middleLayer.getComponent('middleLayer').reloadBundle();
			}
		})

		const time = 0.9;
		btn.scale = 0;
		cc.tween(btn)
			.delay(2.5)
			.to(time,  {scale: btn.baseS}, {easing: "elasticOut"})
			.start();

	},



	async showOneFirework(pos, parentNode, nodeList, w, h, n, timeRate=1) {

		for (let i = 0; i < 3; i++) {
				this.showFirework(pos, parentNode, nodeList, w, h, n, timeRate);
				await asyncDelay(0.1);
		}
	},

	showFirework(pos, parentNode, nodeList, width = 200, height = 500, number = 30, timeRate=1) {
			const subTime = 1;
			for (let i = 0; i < number; i++) {
					const quad = this.createQuads(pos, parentNode, nodeList);
					const targetX = RandomInt(width / 2, -width / 2);
					const targetY = RandomInt(height);

					cc.tween(quad)
							.by(0.5 * timeRate, { x: targetX })
							.by((2 + subTime *  Math.random()) * timeRate, { x: targetX * 2 })
							.start();

					cc.tween(quad)
							.by(0.5 * timeRate, { y: targetY }, { easing: 'quadOut' })
							.to((3 + subTime * Math.random()) * timeRate, { y: -parentNode.height * 2 }, { easing: 'quadIn' })
							.removeSelf()
							.start();

					cc.tween(quad)
							.delay(1  * timeRate)
							.to((0.5 + subTime * Math.random()) * timeRate , { opacity: 0 })
							.start();
			}
	},

	createQuads(pos, parentNode, nodeList) {
			const quadBase = cc.instantiate(nodeList[RandomInt(nodeList.length)]);

			quadBase.x = pos.x;
			quadBase.y = pos.y;
			quadBase.z = pos.z;
			quadBase.angle = RandomInt(180);
			quadBase.parent = parentNode;

			const quad = quadBase.getChildByName('quad');
			quad.x = 0;
			quad.y = 0;
			quad.angle = RandomInt(180);

			const paper = quad.getChildByName('paper');
			paper.scaleX = Math.random() * 0.8 + 0.2;
			paper.scaleY = Math.random() * 0.8 + 0.2;

			quadBase.scaleX = Math.random();
			cc.tween(quadBase)
					.to((1 - quadBase.scaleX) * 0.3, { scaleX: 1 })
					.call(() => {
							const time = Math.random() * 0.2;
							cc.tween(quadBase)
									.to(0.1 + time, { scaleX: -1 })
									.to(0.1 + time, { scaleX: 1 })
									.union()
									.repeatForever()
									.start();
					})
					.start();


			return quadBase;
	},

















	initHotZone() {
		this.initHotZoneBg();
	},


	hotZoneBg: null,
	initHotZoneBg() {
		this.hotZoneBg = new cc.Node();
		this.hotZoneBg.name = 'hotZoneBg';
		this.hotZoneBg.parent = cc.find('Canvas');
		this.hotZoneBg.zIndex = 4;

		if (!this.data.bgItem) {
			return;
		}

		cc.loader.load({url: this.data.bgItem.url}, (err, img) => {

			// this.addMask(this.hotZoneBg);

			this.hotZoneBg.width = img.width;
			this.hotZoneBg.height = img.height;



			const sprNode = new cc.Node();
			sprNode.name = 'bgItemSpr'
			var sf = new cc.SpriteFrame(img);
			// const spr = this.hotZoneBg.addComponent(cc.Sprite);
			const spr = sprNode.addComponent(cc.Sprite);
			spr.spriteFrame = sf
			sprNode.width = this.hotZoneBg.width;
			sprNode.height = this.hotZoneBg.height;
			sprNode.parent = this.hotZoneBg;
			window['bg'] =sprNode 


			const sx = this.canvas.width / this.hotZoneBg.width;
			const sy = (this.canvas.height) / this.hotZoneBg.height;
			const s = Math.min(sx, sy);
			this.hotZoneBg.scale = s;

			// this.data.bgItem.isShowDebugLine = true;
			this.initHotZoneItem();


	
		});

	},

	initHotZoneItem() {

		this.picNodeArr = [];

		this.data.hotZoneItemArr.forEach((item) => {
			// console.log('item.gIdx: ', item.gIdx);
			switch (item.gIdx) {
				case "0":
					this.setOneHotZonePic(item);
					break;
						
				default:
					break;
			}

		});

	},


	addMask(node) {
		const mask = node.addComponent(cc.Mask);
		mask.type = cc.Mask.Type.RECT;
	},


	setOneDragAction(data) {

		const rate =  (this.hotZoneBg.scale * this.hotZoneBg.width) / this.data.bgItem.rect.width;
		const rectNode = new cc.Node();
		rectNode.name = 'rect' + data.index;
		this.hotZoneBg.addChild(rectNode);

		const ctx = rectNode.addComponent(cc.Graphics);
		// 红色矩形
		ctx.lineWidth = 4;
		ctx.strokeColor = cc.Color.BLACK;
		ctx.fillColor = cc.Color.WHITE.setA(100);

		const scale = rate / this.hotZoneBg.scaleY ;

		rectNode.width = data.rect.width * scale;
		rectNode.height = data.rect.height * scale;
		rectNode.x = -this.hotZoneBg.width / 2 + data.rect.x * scale;
		rectNode.y = this.hotZoneBg.height / 2 - data.rect.height * scale - data.rect.y * scale;
		const {x, y, width, height} = rectNode;
		// rectNode.anchorX = rectNode.anchorY = 0;

		if (this.data.bgItem.isShowDebugLine) {
			ctx.rect(-rectNode.width / 2, -rectNode.height / 2, rectNode.width, rectNode.height);
		}
		ctx.stroke();
		ctx.fill();
		rectNode.x += rectNode.width / 2;
		rectNode.y += rectNode.height / 2;

		rectNode.baseX = rectNode.x;
		rectNode.baseY = rectNode.y;
		rectNode.targetOff();

		rectNode.on(cc.Node.EventType.TOUCH_START, () => {

			if (rectNode.isDragEnd) {
				if (rectNode.audioClip) {
					cc.audioEngine.stopAllEffects();
					cc.audioEngine.playEffect(rectNode.audioClip, false, 0.8);
				}
				return;
			}
			this._curShowItem = rectNode;
		})
		

		const realRate = this.hotZoneBg.width / this.data.bgItem.rect.width;
		rectNode.targetPx = -this.hotZoneBg.width / 2 + ( data.dragDot.x - this.data.bgItem.rect.x ) * realRate;
		rectNode.targetPy = this.hotZoneBg.height / 2 - (data.dragDot.y - this.data.bgItem.rect.y) * realRate;


		if (data.audio_url) {
			cc.assetManager.loadRemote(data.audio_url, (err, audioClip) => {
				rectNode.audioClip = audioClip;
			});
		}



		console.log('setOneAction ~~ data: ', data)
		const actionData = data['actionData_' + data.gIdx];
		if (!actionData) {
			return;
		}
		if (actionData.type == 'text') {
			const label = this.setOneActionText(rectNode, actionData);
			label.node.scale = scale * data.fontScale;

			label.node.targetOff();
		
	

			// label.overflow = cc.Label.Overflow.NONE;
			// label.node.setContentSize(new cc.Size(0, lineHeight));
			label["_forceUpdateRenderData"](true);
		
			
		} else if (actionData.type == 'pic') {

			const pic = this.setOneActionPic(rectNode, actionData);

		} else if (actionData.type == 'anima') {

			const anima = this.setOneActionAnima(rectNode, actionData);
		}
	},



	setOneAction(data) {

		const rate =  (this.hotZoneBg.scale * this.hotZoneBg.width) / this.data.bgItem.rect.width;
		const rectNode = new cc.Node();
		rectNode.name = 'rect' + data.index;
		this.hotZoneBg.addChild(rectNode);

		const ctx = rectNode.addComponent(cc.Graphics);
		// 红色矩形
		ctx.lineWidth = 4;
		ctx.strokeColor = cc.Color.BLACK;
		ctx.fillColor = cc.Color.WHITE.setA(100);

		const scale = rate / this.hotZoneBg.scaleY ;

		rectNode.width = data.rect.width * scale;
		rectNode.height = data.rect.height * scale;
		rectNode.x = -this.hotZoneBg.width / 2 + data.rect.x * scale;
		rectNode.y = this.hotZoneBg.height / 2 - data.rect.height * scale - data.rect.y * scale;
		const {x, y, width, height} = rectNode;
		rectNode.anchorX = rectNode.anchorY = 0;

		if (this.data.bgItem.isShowDebugLine) {
			ctx.rect(0, 0, rectNode.width, rectNode.height);
		}
		ctx.stroke();
		ctx.fill();



		console.log('setOneAction ~~ data: ', data)
		const actionData = data['actionData_' + data.gIdx];
		if (!actionData) {
			return;
		}
		if (actionData.type == 'text') {
			const label = this.setOneActionText(rectNode, actionData);
			label.node.scale = scale * data.fontScale;

			// label.overflow = cc.Label.Overflow.NONE;
			// label.node.setContentSize(new cc.Size(0, lineHeight));
			label["_forceUpdateRenderData"](true);
		
			
		} else if (actionData.type == 'pic') {

			const pic = this.setOneActionPic(rectNode, actionData);

		} else if (actionData.type == 'anima') {

			const anima = this.setOneActionAnima(rectNode, actionData);
		}
	},

	setOneActionText(rectNode, actionData) {


		const labelNode = new cc.Node();
		labelNode.parent = rectNode;
		const label = labelNode.addComponent(cc.Label);

		label.font = cc.find('Canvas/res/font/ahronbd-1').getComponent(cc.Label).font;
		label.string = actionData.text;
		// label.string = `<size=${size}><color=#751e00>${this.curGroup.title }</color></size>`
		// label.lineHeight = size;
		// label.horizontalAlign = cc.macro.TextAlignment.LEFT
		// labelNode.anchorX = 0;
		// labelNode.anchorY = 1
		labelNode.color = cc.Color.BLACK;


		const opArr = actionData.changeOption
		// console.log('opArr', opArr);


		const tweenArr = [];

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

			const opData = opArr[i];
			console.log('opArr[0]', opArr[i])
			if (opData[0] == 'fontColor') {
				const color = new cc.Color();
				cc.Color.fromHEX(color, opData[1] );
				labelNode.color = color;

			} else if (opData[0] == 'opacity') {
				// console.log('opData: ', opData)
				labelNode.opacity = Number( opData[1] / 100 * 255 ) + 0.1;
				// console.log(labelNode.opacity);
				tweenArr.push({item: labelNode , option: `{"${opData[0]}" : ${opData[2] / 100 * 255}}`, optionName: opData[0]},)

			} else {
				label[opData[0]] = opData[1];
				tweenArr.push({item: label, option: `{"${opData[0]}" : ${opData[2]}}`, optionName: opData[0]})

			}
		}


		// if (actionData.audio_url) {
		// 	cc.assetManager.loadRemote(actionData.audio_url, (err, audioClip) => {
		// 		labelNode.audioClip = audioClip;
		// 	});
		// }


		label.lineHeight = label.fontSize;

		// labelNode.y += rectNode.height / 2;
		// labelNode.x += rectNode.width / 2;
		

		// rectNode.addComponent(cc.Button);
		// rectNode.on('click', () => {

		// 	if (labelNode.audioClip) {
		// 		cc.audioEngine.stopAllEffects();
		// 		cc.audioEngine.playEffect(labelNode.audioClip, false, 0.8);
		// 	}

		// 	if (labelNode.isClicked) {
		// 		// return;
		// 	}
		// 	labelNode.isClicked = true;

		// 	for (let i=0; i<tweenArr.length; i++) {
		// 		const tweenData = tweenArr[i];

		// 		if (tweenData.optionName == 'opacity') {
		// 			console.log('~~~ ',  tweenData.item[tweenData.optionName] );

		// 			cc.tween(tweenData.item)
		// 				.to(actionData.changeTime,  JSON.parse(tweenData.option) )
		// 				.start();
		// 		}
				

		// 	}

		// });


		return label;
	},

	setOneActionPic(rectNode, actionData) {

		console.log('setOneActionPic actionData: ', actionData)
		const picNode = new cc.Node();
		rectNode.addChild(picNode);

		cc.loader.load({url: actionData.pic_url}, (err, img) => {

			const spr = picNode.addComponent(cc.Sprite);
			spr.spriteFrame = new cc.SpriteFrame(img)

			picNode.y += rectNode.height / 2;
			picNode.x += rectNode.width / 2;

			picNode.scaleX = rectNode.width / picNode.width;
			picNode.scaleY = rectNode.height / picNode.height;

			const opArr = actionData.changeOption	
			const tweenArr = [];
	
			for (let i = 0; i < opArr.length; i++ ) {
	
				const opData = opArr[i];
				console.log('opData: ~~~ ', opData);

				if (opData[0] == 'opacity') {
					picNode.opacity = Number( opData[1] / 100 * 255 ) + 0.1;
					console.log(picNode.opacity);
					tweenArr.push({item: picNode , option: `{"${opData[0]}" : ${opData[2] / 100 * 255}}`, optionName: opData[0]},)
	
				}  else {
					// picNode[opData[0]] = Number(opData[1]);
					// tweenArr.push({item: picNode, option: `{"${opData[0]}" : ${opData[2]}}`, optionName: opData[0]})
				}

	
				if (actionData.audio_url) {
					cc.assetManager.loadRemote(actionData.audio_url, (err, audioClip) => {
						rectNode.audioClip = audioClip;
					});
				}
				

				rectNode.addComponent(cc.Button);
				rectNode.on('click', () => {

					if (rectNode.audioClip) {
						cc.audioEngine.stopAllEffects();
						cc.audioEngine.playEffect(rectNode.audioClip, false, 0.8);
					}
		
					if (rectNode.isClicked) {
						// return;
					}
					rectNode.isClicked = true;

					for (let i=0; i<tweenArr.length; i++) {
						const tweenData = tweenArr[i];
		
						if (tweenData.optionName == 'opacity') {
							cc.tween(tweenData.item)
								.to(actionData.changeTime,  JSON.parse(tweenData.option) )
								.start();
						}
					}
		
				});
			}

		});
	},

	setOneActionAnima(rectNode, actionData) {


		const animaNode = new cc.Node();
		rectNode.addChild(animaNode);

		if (actionData.audio_url) {
			cc.assetManager.loadRemote(actionData.audio_url, (err, audioClip) => {
				rectNode.audioClip = audioClip;
			});
		}

		const data = actionData;

		const dragonDisplay = animaNode.addComponent(dragonBones.ArmatureDisplay);
		if (!data.texPngData) {
			return
		}



		const image = data.texPngData.url//"http://staging-teach.cdn.ireadabc.com/5a0c5af3e952acd0ac83a6e5c6f03ff1.png";
		const ske = data.skeJsonData.url//"http://staging-teach.cdn.ireadabc.com/bd825dcceea298d1146be8067ae3d17f.json";
		const atlas = data.texJsonData.url//"http://staging-teach.cdn.ireadabc.com/246f8991b729fa3e5a7f4802de828efa.json";
		cc.loader.load(image, (error, texture) => {

			cc.loader.load({url: atlas, type: 'txt'}, (error, atlasJson) => {

				cc.loader.load({url: ske, type: 'txt'}, (error, dragonBonesJson) => {

					if (this.isDestroy) {
						return;
					}

					const atlas = new dragonBones.DragonBonesAtlasAsset();
					atlas.atlasJson = atlasJson;
					atlas.texture = texture;

					const asset = new dragonBones.DragonBonesAsset();
					asset.dragonBonesJson = dragonBonesJson;

					dragonDisplay.dragonAtlasAsset = atlas;
					dragonDisplay.dragonAsset = asset;


					let json = JSON.parse(asset.dragonBonesJson);
					let armatures = json["armature"];
					let armatureNames = [];
					for (let i = 0; i < armatures.length; i++) {
						armatureNames.push(armatures[i].name);
					}
					// console.log('armatureNames: ', armatureNames);

					let animationNames = [];

					if (armatureNames.length > 0) {
						let defaultArmatureName = armatureNames[0];
						dragonDisplay.armatureName = defaultArmatureName;
						// let animationNames = dragonDisplay.getAnimationNames(defaultArmatureName);
						let defaultArmature = armatures[0];
						let animations = defaultArmature.animation;
						for (let i = 0; i < animations.length; i++) {
							animationNames.push(animations[i].name);
						}

						// rectNode.addComponent(cc.Button);
						// rectNode.on('click', () => {
						// 	if (rectNode.isClicked) {
						// 		// return;
						// 	}
						// 	rectNode.isClicked = true;
						// 	console.log('clicked');

						// 	if (rectNode.audioClip) {
						// 		cc.audioEngine.stopAllEffects();
						// 		cc.director.emit('STOP_ALL_AUDIO')
						// 		cc.audioEngine.playEffect(rectNode.audioClip, false, 0.8);
						// 	}

						// 	if (animationNames.length > 0) {
						// 		dragonDisplay.playAnimation(animationNames[0], 1);
						// 	}
						// });
					}


					// animaNode.x = rectNode.x + rectNode.width / 2;
					// animaNode.y = rectNode.y + rectNode.height / 2;

					// const sx = rectNode.width / animaNode.width;
					// const sy = rectNode.height / animaNode.height;
					// const scale = Math.min(sx, sy);
					// animaNode.scale = scale;
					


			


					animaNode.y += rectNode.height / 2;
					animaNode.x += rectNode.width / 2;

					animaNode.scaleX = rectNode.width / animaNode.width;
					animaNode.scaleY = rectNode.height / animaNode.height;
		
					const opArr = actionData.changeOption	
					const tweenArr = [];
			
					for (let i = 0; i < opArr.length; i++ ) {
			
						const opData = opArr[i];
						console.log('opData: ~~~ ', opData);
		
						if (opData[0] == 'opacity') {
							animaNode.opacity = Number( opData[1] / 100 * 255 ) + 0.1;
							console.log(animaNode.opacity);
							tweenArr.push({item: animaNode , option: `{"${opData[0]}" : ${opData[2] / 100 * 255}}`, optionName: opData[2] == null ? '' : opData[0]},)
			
						}  else {
							// animaNode[opData[0]] = Number(opData[1]);
							// tweenArr.push({item: animaNode, option: `{"${opData[0]}" : ${opData[2]}}`, optionName: opData[2] == null ? '' : opData[0]})
						}
		
			
						if (actionData.audio_url) {
							cc.assetManager.loadRemote(actionData.audio_url, (err, audioClip) => {
								rectNode.audioClip = audioClip;
							});
						}
						
		
						rectNode.addComponent(cc.Button);
						rectNode.on('click', () => {
		
							if (rectNode.audioClip) {
								cc.audioEngine.stopAllEffects();
								cc.audioEngine.playEffect(rectNode.audioClip, false, 0.8);
							}
				
							if (rectNode.isClicked) {
								// return;
							}
							rectNode.isClicked = true;
		
							for (let j=0; j<tweenArr.length; j++) {
								const tweenData = tweenArr[j];
				
								console.log('tweenData: ', tweenData);

								if (tweenData.optionName) {

									cc.tween(tweenData.item)
										.to(actionData.changeTime,  JSON.parse(tweenData.option))
										.start();

								}

							}
						
							if (animationNames.length > 0) {
								dragonDisplay.playAnimation(animationNames[0], 1);
							}
				
						});
					}
		
					
				});
			});
		});

	},
	



	setOneAnimaSmall(data) {


		const rate = (this.hotZoneBg.scale * this.hotZoneBg.width) / this.data.bgItem.rect.width;

		const rectNode = new cc.Node();
		rectNode.name = 'rect' + data.index;
		this.hotZoneBg.addChild(rectNode);


		const ctx = rectNode.addComponent(cc.Graphics);
		// 红色矩形
		ctx.lineWidth = 4;
		ctx.strokeColor = cc.Color.BLACK;
		ctx.fillColor = cc.Color.WHITE.setA(100);

		const scale = rate / this.hotZoneBg.scaleY;

		rectNode.width = data.rect.width * scale;
		rectNode.height = data.rect.height * scale;
		rectNode.x = -this.hotZoneBg.width / 2 + data.rect.x * scale;
		rectNode.y = this.hotZoneBg.height / 2 - data.rect.height * scale - data.rect.y * scale;

		rectNode.anchorX = rectNode.anchorY = 0;


		if (this.data.bgItem.isShowDebugLine) {
			ctx.rect(0, 0, rectNode.width, rectNode.height);
		}
		ctx.stroke();
		ctx.fill();




		const animaNode = new cc.Node();
		animaNode.name = 'anima_' + data.index;
		this.hotZoneBg.addChild(animaNode);



		if (data.audio_url) {
			cc.assetManager.loadRemote(data.audio_url, (err, audioClip) => {
				animaNode.audioClip = audioClip;
			});
		}


		const dragonDisplay = animaNode.addComponent(dragonBones.ArmatureDisplay);
		if (!data.texPngData) {
			return
		}
		
		const image = data.texPngData.url//"http://staging-teach.cdn.ireadabc.com/5a0c5af3e952acd0ac83a6e5c6f03ff1.png";
		const ske = data.skeJsonData.url//"http://staging-teach.cdn.ireadabc.com/bd825dcceea298d1146be8067ae3d17f.json";
		const atlas = data.texJsonData.url//"http://staging-teach.cdn.ireadabc.com/246f8991b729fa3e5a7f4802de828efa.json";
		cc.loader.load(image, (error, texture) => {

			cc.loader.load({url: atlas, type: 'txt'}, (error, atlasJson) => {

				cc.loader.load({url: ske, type: 'txt'}, (error, dragonBonesJson) => {

					if (this.isDestroy) {
						return;
					}

					const atlas = new dragonBones.DragonBonesAtlasAsset();
					atlas.atlasJson = atlasJson;
					atlas.texture = texture;

					const asset = new dragonBones.DragonBonesAsset();
					asset.dragonBonesJson = dragonBonesJson;

					dragonDisplay.dragonAtlasAsset = atlas;
					dragonDisplay.dragonAsset = asset;

					

					let json = JSON.parse(asset.dragonBonesJson);
					let armatures = json["armature"];
					// console.log('armatures: ', armatures);
					let armatureNames = [];
					for (let i = 0; i < armatures.length; i++) {
						armatureNames.push(armatures[i].name);
					}
					// console.log('armatureNames: ', armatureNames);
					if (armatureNames.length > 0) {
						let defaultArmatureName = armatureNames[0];
						dragonDisplay.armatureName = defaultArmatureName;
						// let animationNames = dragonDisplay.getAnimationNames(defaultArmatureName);
						let defaultArmature = armatures[0];
						let animations = defaultArmature.animation;
						let animationNames = [];
						for (let i = 0; i < animations.length; i++) {
							animationNames.push(animations[i].name);
						}

						rectNode.addComponent(cc.Button);
						rectNode.on('click', () => {
							if (rectNode.isClicked) {
								// return;
							}
							rectNode.isClicked = true;
							console.log('clicked');

							if (animaNode.audioClip) {
								cc.audioEngine.stopAllEffects();
								cc.director.emit('STOP_ALL_AUDIO')
								cc.audioEngine.playEffect(animaNode.audioClip, false, 0.8);
							}

							if (animationNames.length > 0) {
								dragonDisplay.playAnimation(animationNames[0], 1);
							}
						});
					}


					animaNode.x = rectNode.x + rectNode.width / 2;
					animaNode.y = rectNode.y + rectNode.height / 2;

					const sx = rectNode.width / animaNode.width;
					const sy = rectNode.height / animaNode.height;
					const scale = Math.min(sx, sy);
					animaNode.scale = scale;
					
				});
			});
		});

	},

	setOneHotZonePic(data) {
		const rate = (this.hotZoneBg.scale * this.hotZoneBg.width) / this.data.bgItem.rect.width;

		const picNode = new cc.Node();
		picNode.name= 'pic' + data.index;
		picNode.data = data;
		this.hotZoneBg.addChild(picNode);

		this.picNodeArr.push(picNode);
		picNode.hitCount = 0;

		cc.loader.load({url: data.pic_url}, (err, img) => {

			const spr = picNode.addComponent(cc.Sprite);
			spr.spriteFrame = new cc.SpriteFrame(img)

			const scale = rate / this.hotZoneBg.scaleY;

			picNode.width = data.rect.width * scale;
			picNode.height = data.rect.height * scale;
			picNode.x = -this.hotZoneBg.width / 2 + data.rect.x * scale;
			picNode.y = this.hotZoneBg.height / 2 - data.rect.height * scale - data.rect.y * scale;

			picNode.x += picNode.width / 2 * picNode.scaleX;
			picNode.y += picNode.height / 2 * picNode.scaleX;


			getSprNodeByUrl(data.answer_pic_url, (spr) => {

				const sprNode = spr.node;
				sprNode.active = false;
				picNode.addChild(sprNode);
				picNode.answerPic = sprNode;

				picNode.isLoadEnd = true;
				this.checkStart();
			})

			// picNode.anchorX = picNode.anchorY = 0;

			// if (data.audio_url) {
			// 	this.addPicAudio(picNode);
			// }

			// this.addDragPoint(picNode, data)

		});

	},

	addDragPoint(picNode, data) {


		picNode.baseX = picNode.x;
		picNode.baseY = picNode.y;

		const realRate = this.hotZoneBg.width / this.data.bgItem.rect.width;
		picNode.targetPx = -this.hotZoneBg.width / 2 + ( data.dragDot.x - this.data.bgItem.rect.x ) * realRate;
		picNode.targetPy = this.hotZoneBg.height / 2 - (data.dragDot.y - this.data.bgItem.rect.y) * realRate;


		if (data.audio_url) {
			cc.assetManager.loadRemote(data.audio_url, (err, audioClip) => {
				picNode.audioClip = audioClip;
			});
		}


		picNode.on(cc.Node.EventType.TOUCH_START, () => {
			if (picNode.isDragEnd) {
				if (picNode.audioClip) {
					cc.audioEngine.stopAllEffects();
					cc.audioEngine.playEffect(picNode.audioClip, false, 0.8);
				}
				return;
			}
			this._curShowItem = picNode;

			// picNode.x = -this.hotZoneBg.width / 2 + ( data.dragDot.x - this.data.bgItem.rect.x ) * realRate;
			// picNode.y = this.hotZoneBg.height / 2 - (data.dragDot.y - this.data.bgItem.rect.y) * realRate;

		})
	},


	setOnePic(data) {
		const rate = (this.hotZoneBg.scale * this.hotZoneBg.width) / this.data.bgItem.rect.width;

		const picNode = new cc.Node();
		picNode.name= 'pic' + data.index;
		picNode.data = data;
		this.hotZoneBg.addChild(picNode);

		getSprNodeByUrl(data.pic_url, (spr) => {

			const sprNode = spr.node;
			picNode.addChild(sprNode);

			const scale = rate / this.hotZoneBg.scaleY;

			picNode.width = sprNode.width = data.rect.width * scale;
			picNode.height = sprNode.height = data.rect.height * scale;
			picNode.x = -this.hotZoneBg.width / 2 + data.rect.x * scale;
			picNode.y = this.hotZoneBg.height / 2 - data.rect.height * scale - data.rect.y * scale;

			// sprNode.anchorX = sprNode.anchorY = 0;


		})


		// cc.loader.load({url: data.pic_url}, (err, img) => {

		// 	const spr = picNode.addComponent(cc.Sprite);
		// 	spr.spriteFrame = new cc.SpriteFrame(img)

		// 	const scale = rate / this.hotZoneBg.scaleY;

		// 	picNode.width = data.rect.width * scale;
		// 	picNode.height = data.rect.height * scale;
		// 	picNode.x = -this.hotZoneBg.width / 2 + data.rect.x * scale;
		// 	picNode.y = this.hotZoneBg.height / 2 - data.rect.height * scale - data.rect.y * scale;

		// 	picNode.anchorX = picNode.anchorY = 0;

		// 	// if (data.audio_url) {
		// 	// 	this.addPicAudio(picNode);
		// 	// }

		// });

		// picNode.on('touchstart', () => {
		// 	this.show
		// })

	},

	setOneRect(data) {
		const rate = (this.hotZoneBg.scale * this.hotZoneBg.width) / this.data.bgItem.rect.width;

		const rectNode = new cc.Node();
		rectNode.name = 'rect' + data.index;
		this.hotZoneBg.addChild(rectNode);


		const ctx = rectNode.addComponent(cc.Graphics);
		// 红色矩形
		ctx.lineWidth = 4;
		ctx.strokeColor = cc.Color.BLACK;
		ctx.fillColor = cc.Color.WHITE.setA(100);

		const scale = rate / this.hotZoneBg.scaleY;
		// console.log('scale: ', scale);
		// console.log('scale2: ', scale / data.mapScale);


		rectNode.width = data.rect.width * scale;
		rectNode.height = data.rect.height * scale;
		rectNode.x = -this.hotZoneBg.width / 2 + data.rect.x * scale;
		rectNode.y = this.hotZoneBg.height / 2 - data.rect.height * scale - data.rect.y * scale;
		// rectNode.scale = 1 / data.mapScale;

		rectNode.anchorX = rectNode.anchorY = 0;


		if (this.data.bgItem.isShowDebugLine) {
			ctx.rect(0, 0, rectNode.width, rectNode.height);
		}
		ctx.stroke();
		ctx.fill();

		// console.log('```data: ', data)

		this.dragEndRectArr.push(rectNode);

		if (data.audio_url) {
			cc.assetManager.loadRemote(data.audio_url, (err, audioClip) => {
				rectNode.audioClip = audioClip;
			});
		}

		// rectNode.addComponent(cc.Button);
		// rectNode.on('click', () => {
		// 	if (rectNode.isClicked) {
		// 		// return;
		// 	}
		// 	rectNode.isClicked = true;
		// 	console.log('clicked');

		// 	if (rectNode.audioClip) {
		// 		cc.audioEngine.stopAllEffects();
		// 		cc.audioEngine.playEffect(rectNode.audioClip, false, 0.8);
		// 	}
		// });


	},

	addPicAudio(picNode) {
		const data = picNode.data;
		
		cc.assetManager.loadRemote(data.audio_url, (err, audioClip) => {
			picNode.audioClip = audioClip;
		});

		picNode.addComponent(cc.Button);
		picNode.on('click', () => {
				if (picNode.audioClip) {
					cc.audioEngine.stopAllEffects();
					cc.audioEngine.playEffect(picNode.audioClip, false, 0.8);
				}
		});
	},


	initListener() {

		const canvas = cc.find('Canvas');
		
		let downFlag = false;

		const touchMove = (e) => {
			this.canvasTouchMove(e);
			if (canvas.hasEventListener(cc.Node.EventType.MOUSE_MOVE)) {
				canvas.off(cc.Node.EventType.MOUSE_MOVE, mouseMove)
			}
		}

		const mouseMove = (e) => {
			if (!downFlag) {
				return;
			}
			this.canvasTouchMove(e);
			if (canvas.hasEventListener(cc.Node.EventType.TOUCH_MOVE)) {
				canvas.off(cc.Node.EventType.TOUCH_MOVE, touchMove)
				this.removeHtmlCanvasListener('touchmove');
			}
		}

		const touchEnd = (e) => {
		
			downFlag = false;
			this.canvasTouchEnd(e);

			if (canvas.hasEventListener(cc.Node.EventType.MOUSE_UP)) {
				canvas.off(cc.Node.EventType.MOUSE_UP, mouseUp)
			}
			if (canvas.hasEventListener(cc.Node.EventType.MOUSE_LEAVE)) {
				canvas.off(cc.Node.EventType.MOUSE_LEAVE, mouseUp)
			}
			this.removeHtmlTouchEnd();
		}

		const mouseUp = (e) => {
	
			downFlag = false;

			this.canvasTouchEnd(e);

			if (canvas.hasEventListener(cc.Node.EventType.TOUCH_END)) {
				canvas.off(cc.Node.EventType.TOUCH_END, touchEnd)
			}
			if (canvas.hasEventListener(cc.Node.EventType.TOUCH_CANCEL)) {
				canvas.off(cc.Node.EventType.TOUCH_CANCEL, touchEnd)
			}
		}
		

		canvas.on(cc.Node.EventType.TOUCH_MOVE, touchMove)
		canvas.on(cc.Node.EventType.MOUSE_MOVE, mouseMove)

		canvas.on(cc.Node.EventType.TOUCH_END, touchEnd)
		canvas.on(cc.Node.EventType.TOUCH_CANCEL, touchEnd)
		canvas.on(cc.Node.EventType.MOUSE_UP, mouseUp)

	},

	removeHtmlCanvasListener(type) {
		const canvasHtml = document.querySelector('canvas');
		canvasHtml.addEventListener(type, (e) => {})
	},	
	removeHtmlTouchEnd() {
		const canvasHtml = document.querySelector('canvas');
		canvasHtml.removeEventListener('touchend', this.htmlCanvasTouchendFunc, this);
	},

	canvasTouchMove(e) {

		if (!this._curShowItem) {
			return;
		}
		const pos = e.getLocation();
		this._curShowItem.x = pos.x - e.currentTarget.width / 2;
		this._curShowItem.y = pos.y - e.currentTarget.height / 2;

		// console.log('pos: ', pos.x);
	},

	canvasTouchEnd(e) {

		if (!this._curShowItem) {
			return;
		}
		this.checkOnDragEndRect();
		this._curShowItem = null;
	},



	checkOnDragEndRect() {

		console.log('emptyGroupArr: ',  this.emptyGroupArr);
		for (let i = 0; i < this.dragEndRectArr.length; i++) {

			const rect = this.dragEndRectArr[i];

			const worldPos = this._curShowItem.parent.convertToWorldSpaceAR(cc.v2(this._curShowItem.x, this._curShowItem.y));
			const worldRect = rect.getBoundingBoxToWorld();
			if (worldRect.contains(worldPos)) {
			
				console.log('rect in ')
				this.checkIsDragEndTarget(rect);
				// removeItemFromArr(this.emptyGroupArr, letterGroup);
				// this.showLetterSuccess(letterGroup);
				// this.checkGroupEnd();
				return;
			}
			
		}

		this.itemBack();
	},

	itemBack() {

		cc.audioEngine.playEffect(this.wrongClip, false, 0.8);

		cc.tween(this._curShowItem)
			.to(0.5, {x: this._curShowItem.baseX, y: this._curShowItem.baseY}, {easing: "elasticOut"})
			.start();
	},

	checkIsDragEndTarget(rect) {

		const worldPos = this._curShowItem.parent.convertToWorldSpaceAR(cc.v2(this._curShowItem.targetPx, this._curShowItem.targetPy));
		const worldRect = rect.getBoundingBoxToWorld();
		if (worldRect.contains(worldPos)) {
			this._curShowItem.x = this._curShowItem.targetPx;
			this._curShowItem.y = this._curShowItem.targetPy;
			this._curShowItem.isDragEnd = true;


			cc.audioEngine.playEffect(this.rightClip, false, 0.8);

		} else {
			this.itemBack();
		}
	},


	onDestroy() {
		this.isDestroy = true;
		this._timeoutIds.forEach(id => {
			clearTimeout(id);
		});
		this._intervalIds.forEach(id => {
			clearInterval(id);
		});
	}

});
