<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="xhtml-default.css" type="text/css" media="screen, aural, print" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
    "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" >
<head>
<link rel="shortcut icon" href="sgc.png" />
<link rel="icon" sizes="192x192" href="sgc.png" />
<link rel="manifest" href="manifest.json" />
<meta name="viewport" content="width=device-width" />
<meta name="mobile-web-app-capable" content="yes" />
<meta http-equiv="Content-Language" content="en" />
<title lang="en" xml:lang="en" dir="ltr">SpeakGoodChinese 3</title>
<style>
body {
	background-image: url("Background.png");
	background-color: rgb(250,250,250);
    background-repeat: no-repeat;
    background-position: center center;
    background-attachment: fixed;}
h1 {
	text-align: center;
	}
button {
		position: fixed;
		overflow: hidden;
		text-overflow: clip clip;
		width:17%;
		height:15%;
		cursor:pointer; /*forces the cursor to change to a hand when the button is hovered*/
		text-align:center;
		font: bold 4vmin "Helvetica";
		background-color: rgb(220,220,220);
		text-overflow: clip;
		
		-webkit-box-shadow: inset 0px 1px 0px #3e9cbf, 0px 5px 0px 0px #205c73, 0px 10px 5px #999;
		-moz-box-shadow: inset 0px 1px 0px #3e9cbf, 0px 5px 0px 0px #205c73, 0px 10px 5px #999;
		box-shadow: inset 0px 1px 0px #3e9cbf, 0px 5px 0px 0px #205c73, 0px 10px 5px #999;
		
		/*give the corners a small curve*/
		-moz-border-radius: 7px;
		-webkit-border-radius: 7px;
		border-radius: 7px;
		}

</style>

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />

<script type="text/javascript" src="wordlists.js" ></script>   
<script type="text/javascript" src="wordlists_plus.js" ></script>   
<script type="text/javascript" src="internationalization_tables.js" ></script>   
<script type="text/javascript" src="audioProcessing.js" ></script>   
<script type="text/javascript" src="toneprot.js" ></script>   
<script type="text/javascript" src="RecordRTC.min.js" defer="true" ></script> 
<script type="text/javascript" src="jszip.min.js" defer="true" ></script> 
<script type="text/javascript" src="mespeak/mespeak.full.js" defer="true" ></script>
<script type="text/javascript" src="fft.js/lib/real.js" defer="true" ></script>
<script type="text/javascript" src="fft.js/lib/complex.js" defer="true" ></script>
</head>

<body onload="if(window.speechSynthesis)window.speechSynthesis.getVoices();localStorage.sgc3_saveAudio = JSON.stringify(false);" onfocus="load_SGC3_settings ();" onblur="store_SGC3_settings ();" onunload="sgc3_settings.saveAudio = false; store_SGC3_settings (); if(settingsWindow)settingsWindow.close(); if(selectWordsWindow)selectWordsWindow.close();" contextmenu="mymenu" >
<!--
SpeakGoodChinese 3
Copyright (C) 2016 R.J.J.H. van Son (r.j.j.h.vanson@gmail.com)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You can find a copy of the GNU General Public License at
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-->
	<menu type="context" id="mymenu" hidden='true' >
		<menu type="context" id="GRADE" label="Grade" icon="sgc.png" title="Grade" >
			<menuitem id="GRADE1" label="1" onclick="setGRADE(currentPinyin, 1);" icon="sgc.png" title="1" ></menuitem>
			<menuitem id="GRADE2" label="2" onclick="setGRADE(currentPinyin,2);" icon="sgc.png" title="2" ></menuitem>
			<menuitem id="GRADE3" label="3" onclick="setGRADE(currentPinyin,3);" icon="sgc.png" title="3" ></menuitem>
			<menuitem id="GRADE4" label="4" onclick="setGRADE(currentPinyin,4);" icon="sgc.png" title="4" ></menuitem>
			<menuitem id="GRADE5" label="5" onclick="setGRADE(currentPinyin,5);" icon="sgc.png" title="5" ></menuitem>
			<menuitem id="GRADE6" label="6" onclick="setGRADE(currentPinyin,6);" icon="sgc.png" title="6" ></menuitem>
			<menuitem id="GRADE7" label="7" onclick="setGRADE(currentPinyin,7);" icon="sgc.png" title="7" ></menuitem>
			<menuitem id="GRADE8" label="8" onclick="setGRADE(currentPinyin,8);" icon="sgc.png" title="8" ></menuitem>
			<menuitem id="GRADE9" label="9" onclick="setGRADE(currentPinyin,9);" icon="sgc.png" title="9" ></menuitem>
			<menuitem id="GRADE10" label="10" onclick="setGRADE(currentPinyin,10);" icon="sgc.png" title="10" ></menuitem>
		</menu>
	</menu>

	<div style="color: rgb(220,220,220); position: fixed; bottom: 36%; right: 2%; width: 17%; height: 5%; font-size: 3vmin; text-align: center; text-overflow: clip; vertical-align: bottom; " id="CollectionString" align="center"></div>
 	<div style="color: rgb(220,220,220); position: fixed; bottom: 24%; right: 2%; height: 14%; width: 17%; font-size: 6vmin; text-align: center; vertical-align: top; " id="SaveAudioLight" contextmenu="mymenu" ><a href="javascript:gradePrompt()" id='GradePrompt' style="color: inherit; text-decoration:none; " >&#9679; <br/>
 	<span id="GradeString" style="font-style: italic; font-size: 5vmin; "></span></a>
 	</div>
 	
 		
	<div style="color: gray; position: fixed; top: 5%; left: 5%; font-size: 15vmin" id="RecordingLight">&#9679;</div>
	<p><audio id='ExampleAudio' controls="false" hidden="true" ></audio></p>
	<canvas id="TonePlot" width="1000" height="1000" style="position: fixed; top: 5%; left: 22.5%; width: 55%; height: 55%; "></canvas> 	
	
	<div id="DisplayText" title="" >
	<div style="color: black; position: fixed; top: 60%; left: 10%; width: 70%; font-size: 6vmin; text-align: center; " id="DisplayString" align="center" >
		<span id="Pinyin">-</span>&#8195;<span id="Character">-</span>&#8195;<span id="Translation" style="font-style: italic; font-size: 6vmin; ">-</span></div>
	<div style="color: green; position: fixed; top: 68%; left: 20%; width: 60%; font-size: 4vmin; text-align: center; text-overflow: clip; " id="ResultString" align="center">---</div>
	<div style="color: green; position: fixed; top: 73%; left: 20%; width: 60%; font-size: 4vmin; text-align: center; text-overflow: clip; " id="FeedbackString" align="center">---</div>
	</div>
	
	
	<div style="color: blue; position: fixed; bottom: 18%; left: 5%; width: 90%; font-size: 3vmin; text-align: center; text-overflow: clip; " id="WordlistString" align="center">---</div>
	
	<canvas id="LeftProgress" width="1000" height="2" style="position: fixed; bottom: 18%; left: 6%; width: 15%; height: 4px; "></canvas>
	<button type="button" style="color: black; bottom: 2%; left: 5%" id="PreviousButton" ><span style="font-size: 100%">|&#9664;<br /><span id="Previous" >Previous</span></span></button>
	<button type="button" style="color: gray; bottom: 2%; left: 23%" id="RecordButton" disabled="true" ><span style="font-size: 100%; ">&#9679;<br /><span id="Record" >Record</span></span></button>
	<button type="button" style="color: gray; bottom: 2%; left: 41%" id="PlayButton" disabled="true" ><span style="font-size: 100%">&#9658;<br /><span id="Play" >Play</span></span></button>
	<button type="button" style="color: black; bottom: 2%; left: 59%" id="ExampleButton" ><span style="font-size: 100%">&#9658;<br /><span id="Example" >Example</span></span></button>
	<canvas id="RightProgress" width="1000" height="2" style="position: fixed; bottom: 18%; left: 78%; width: 15%; height: 4px; "></canvas>
	<button type="button" style="color: black; bottom: 2%; left: 77%; " id="NextButton" ><span style="font-size: 100%">&#9654;|<br /><span id="Next" >Next</span></span></button>

	<button type="button" style="color: black; bottom: 84%; right: 2%; height: 10%" id="Settings" ><span style="font-size: 100%">&#8594; <span id="Config" >Settings</span></span></button>

	<!-- Wordlists -->
	<button type="button" style="color: black; bottom: 71%; right: 2%; height: 10%" id="PreviousWordlist" ><span style="font-size: 100%"><span id="WordlistUp" >Previous</span> &#8593;</span></button>
	<button type="button" style="color: black; bottom: 50%; right: 2%; height: 10%" id="NextWordlist" ><span style="font-size: 100%"> <span id="WordlistDown" title="" >Next</span> &#8595;</span></button>
	<select id="SelectWordList" style="position: fixed; color: black; bottom: 61%; right: 2%; height: 8%; width: 17%; font: 3vmin 'Helvetica'; background-color: rgb(220,220,220); "  >
		<option value="---" ><span id="SelectWords" title="" >Words</span></option>
		<option value="---" ><span id="WordlistCaption" title="" >Word List</span></option>
	</select> 

	<select id="Register" style="position: fixed; color: black; bottom: 39%; right: 2%; height: 8%; width: 17%; font: 3.5vmin 'Helvetica'; background-color: rgb(220,220,220); " onchange="sgc3_settings.register = getRegister();" >
		<option value="---" ><span id="RegisterCaption" title="" >---</span></option>
	</select> 

	<select id="Language" style="position: fixed; color: black; bottom: 28%; right: 2%; height: 8%; width: 17%; font: 3.5vmin 'Helvetica'; background-color: rgb(220,220,220); " onchange="sgc3_settings.language = change_mainpageLanguage(); " >
		<option value="---" ><span id="LanguageCaption" title="" >---</span></option>
	</select> 

	<script type="text/javascript">
	//<![CDATA[
	// Install the service worker for offline use
	if ('serviceWorker' in navigator) {
	  navigator.serviceWorker.register('sw.js').then(function(registration) {
	    // Registration was successful
	    console.log('ServiceWorker registration successful with scope: ',    registration.scope);
	  }).catch(function(err) {
	    // registration failed :(
	    console.log('ServiceWorker registration failed: ', err);
	  });
	}
	
	// Set DOM parameters
	var settingsWindow;
	var selectWordsWindow;
	var gradingMenu = document.getElementById('GRADE');
	var gradePromptAnchor = document.getElementById('GradePrompt');
	var recordingLight = document.getElementById('RecordingLight');
	var tonePlotArea = document.getElementById('TonePlot');
	var record = document.getElementById('RecordButton');
	var play = document.getElementById('PlayButton');
	var example = document.getElementById('ExampleButton');
	var previous = document.getElementById('PreviousButton');
	var next = document.getElementById('NextButton');
	var prevWordlist = document.getElementById('PreviousWordlist');
	var nextWordlist = document.getElementById('NextWordlist');
	var selectWordlist = document.getElementById('SelectWordList');
	var exampleElement = document.getElementById('ExampleAudio');
	var settingsButton = document.getElementById('Settings');
	var displayText = document.getElementById('DisplayText');
	var stopRecording, playSound;
	var exampleURL = "-";
	var voiceZH_CN = -1;
	var currentRecordingTime = 3;
	var clearRecordedData = function () { };
	
	// Handle keypresses
	function keyPress (e) {
		var key = e.key ? e.key : e.code;
		if (key == "ArrowRight") {
			next.onclick()
		} else if (key == ">" || key == ".") {
			next.onclick()
		} else if (key == "ArrowLeft") {
			previous.onclick()
		} else if (key == "<" || key == ",") {
			previous.onclick()
		} else if (key == "ArrowUp") {
			prevWordlist.onclick()
		} else if (key == "ArrowDown") {
			nextWordlist.onclick()
		} else if (key == "Tab") {
			play.onclick()
		} else if (key == "Enter") {
			record.onclick()
		} else if (key == " " || key == "Space") {
			example.onclick()
		}  else {
			if (["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"].indexOf(key) > -1) {
				setGRADE(currentPinyin, key);
			};
		};
	};
	window.onkeydown = keyPress;
	
	// Swipes with mouse or touch
	// Adde touch events
	tonePlotArea.addEventListener("touchstart", mouseDown, false);
	tonePlotArea.addEventListener("touchend", mouseUp, false);
	// Parameters
	var verticalThreshold = tonePlotArea.height / 30;
	var horizontalThreshold = tonePlotArea.width / 30;
	var mouseDownCoordinates = {x: -1, y: -1};
	var mouseUpCoordinates = {x: -1, y: -1};
	// Mouse down or touch start
	function mouseDown (e) {
		if (e.touches) e.preventDefault();
		mouseDownCoordinates.x = e.touches ? e.touches[0].clientX : e.clientX;
		mouseDownCoordinates.y = e.touches ? e.touches[0].clientY : e.clientY;
		mouseUpCoordinates.x = -1;
		mouseUpCoordinates.y = -1;
	};
	// Mouse up or touch end
	function mouseUp (e) {
		mouseUpCoordinates.x = e.touches ? e.touches[e.touches.length - 1].clientX : e.clientX;
		mouseUpCoordinates.y = e.touches ? e.touches[e.touches.length - 1].clientY : e.clientY;
		
		if (mouseDownCoordinates.x > -1 && mouseDownCoordinates.y > -1) {
			// Horizontal
			if (Math.abs(mouseUpCoordinates.y - mouseDownCoordinates.y) < verticalThreshold) {
				// To the left
				if(mouseUpCoordinates.x - mouseDownCoordinates.x < -horizontalThreshold) {
					next.onclick();
				// To the right
				} else if(mouseUpCoordinates.x - mouseDownCoordinates.x > horizontalThreshold) {
					previous.onclick();
				};
			} else if (Math.abs(mouseUpCoordinates.x - mouseDownCoordinates.x) < horizontalThreshold) {
			// Vertical
				// Up
				if(mouseUpCoordinates.y - mouseDownCoordinates.y < -verticalThreshold) {
					nextWordlist.onclick();
				// Down
				} else if(mouseUpCoordinates.y - mouseDownCoordinates.y > verticalThreshold) {
					prevWordlist.onclick();
				};
			};
		};

		mouseDownCoordinates.x = -1;
		mouseDownCoordinates.y = -1;
		mouseUpCoordinates.x = -1;
		mouseUpCoordinates.y = -1;

	};
	tonePlotArea.onmousedown = mouseDown;
	tonePlotArea.onmouseup = mouseUp;
	tonePlotArea.onmouseout = mouseUp;
	
	/*
	 * Global variables from audioProcessing.js
	 * 
	 * var recordedBlob, recordedBlobURL;
	 * var recordedArray, currentAudioWindow;
	 * var recordedSampleRate, recordedDuration;
	 * 
	 */
	 
	// Global settings
	// This setting is NOT stored
	localStorage.sgc3_currentWord = JSON.stringify(0);
	sessionStorage.lastPinyin = "";
	localStorage.sgc3_saveAudio = JSON.stringify(false);
	
	// These settings are stored
	var sgc3_settings = {
		settingsRead: false,
		recSecs: 3,
		ttsSpeed: 110,
		ttsVariant: "f3",
		shuffleLists: true,
		register: 249, // Must match Register_249 Id
		wordList: "20 basic tone combinations",
		language: "",
		synthesis_eSpeak: false,
		strict: 1,
		personalWordlists: [],
		displayNumbers: false,
		displayPinyin: true,
		displayChar: true,
		displayTrans: true,
		saveAudio: false,
		examplesDatabaseName: "SGC3 examples",
		audioDatabaseName: "SGC3 audio",
		currentCollection: "SGC3",
		selectedLessons: [],
		selectedTones: [],
		deselectedWords: []
	};
	
	// Store settings
	function store_SGC3_settings () {
		for (x in sgc3_settings) {
			localStorage["sgc3_"+x] = JSON.stringify(sgc3_settings[x]);
		};
		localStorage.sgc3_currentWord = JSON.stringify(currentWord);
	};
	
	function load_SGC3_settings () {
		for (x in sgc3_settings) {
			// For some reason, parsing the language goes wrong
			if (localStorage["sgc3_"+x]) {
				sgc3_settings[x] = JSON.parse(localStorage["sgc3_"+x]);
			};
		};
		
		set_mainpageLanguage (sgc3_settings.language);
		setRegister (sgc3_settings.register);
		if (sgc3_settings.settingsRead) hideSelectors();
		wordlists = combineWordlistLists(global_wordlists, sgc3_settings.personalWordlists);
		get_wordlist(sgc3_settings.wordList);
		add_wordlist_names_to_select ();
		document.getElementById('WordlistString').textContent = sgc3_settings.wordList;
		document.getElementById('SaveAudioLight').style.color = sgc3_settings.saveAudio ? 'blue' : 'rgb(250,250,250)';
		var collectionString = document.getElementById('CollectionString');
		if(collectionString) {
			collectionString.textContent = sgc3_settings.saveAudio ? sgc3_settings.currentCollection : "";
			collectionString.style.fontSize = collectionString.textContent.length > 12 ? "2.5vmin" : "3vmin";
			collectionString.style.color = sgc3_settings.saveAudio ? 'blue' : 'rgb(250,250,250)';
		};

		// Disabling/hiding the menu does not work everywhere
		gradingMenu.disabled = ! sgc3_settings.saveAudio;
		gradingMenu.hidden = ! sgc3_settings.saveAudio;

		// Reset currentWord if the wordlist has changed
		currentWord = 0;
		if (localStorage.sgc3_currentWord) {
			currentWord = JSON.parse(localStorage.sgc3_currentWord);
		};
		if (currentWord < 0){
			clearRecordedData ();
			currentWord = 0;
		};
		// Make sure the current word is indeed active
		while (currentWord < currentWordlist.length && ! itemIsActive (currentWord)) ++currentWord;
		
		// update display
		write_CurrentString ();
		examplesDatabaseName = sgc3_settings.examplesDatabaseName;
		audioDatabaseName = sgc3_settings.audioDatabaseName;

		if(sgc3_settings.saveAudio) getCurrentMetaData (sgc3_settings.currentCollection, function (list){performanceRecord = objectList2performanceRecord(list);});
		
		// Reset the language
		if (!sgc3_settings.language) {
			sgc3_settings.language = (userLanguage) ? userLanguage : "EN";
		};
		set_mainpageLanguage (sgc3_settings.language);
	};
	
	// Initialize to stored settings
	if(localStorage.sgc3_language) {
		load_SGC3_settings ();
	} else {
		// Do hard initialization of stored parameters
		store_SGC3_settings ();
	};
	
	// Set language
	if (!sgc3_settings.language) {
		sgc3_settings.language = (userLanguage) ? userLanguage : "EN";
	};
	set_mainpageLanguage (sgc3_settings.language);
	
	// Set TTS
	function getTTSvoice(){
		var selectedVoice;
		if (window.speechSynthesis) {
			var voices = window.speechSynthesis.getVoices();
			if (! voices) voices = window.speechSynthesis.getVoices();
			for (x = 0; x < voices.length; ++x) {
				if (voices[x].lang == "zh-CN") { 
					voiceZH_CN = x;
					selectedVoice = voices[x];
				};
			};
		}
		return selectedVoice;
	};
	
	if (window.speechSynthesis) {
		window.speechSynthesis.onvoiceschanged = function() {
		    getTTSvoice();
		};
	}

	// Set Register
	setRegister (sgc3_settings.register);
	
	// Hide Language and Register when settings page has been opened
	function hideSelectors () {
		var languageElement = document.getElementById('Language');
		var registerElement = document.getElementById('Register');
		languageElement.style.display = 'none' ;
		registerElement.style.display = 'none' ;
	};

	// Set progress bars
	function setProgressBar (id, fraction) {
		var progressBar = document.getElementById(id);
		var progressBarCtx = progressBar.getContext("2d");
		progressBarCtx.clearRect(0, 0, progressBarCtx.canvas.width, progressBarCtx.canvas.height);
		progressBarCtx.fillStyle = "rgb(250,250,250)";
		progressBarCtx.fillRect(0, 0, progressBarCtx.canvas.width, progressBarCtx.canvas.height);
		progressBarCtx.beginPath();
		progressBarCtx.fillStyle = "#008080";
		if (fraction > 0) {
			progressBarCtx.fillRect(0, 0, progressBarCtx.canvas.width*fraction, progressBarCtx.canvas.height);
		} else {
			progressBarCtx.fillRect(progressBarCtx.canvas.width*(1+fraction), 0, progressBarCtx.canvas.width, progressBarCtx.canvas.height);
		};
		progressBarCtx.stroke();
	};
	
	// Replace contents of displayed string
	function write_CurrentString () {
		// Store current settings
		store_SGC3_settings ()
		
		// Get wordlist
		get_wordlist (sgc3_settings.wordList);
		write_WordlistName();

		// Get texts
		document.getElementById("GradeString").textContent = "";
		var pinyinText = "-";
		var characterText = "-";
		var translationText = "-";
		var lessonText = "-";
		exampleURL = "-";
		if( currentWord >= 0 && currentWord < currentWordlist.length ) {
			currentItem = currentWordlist[currentWord];
			currentLesson = sgc3_settings.wordList;
			currentLesson += (currentItem[4] && currentItem[4] != "-") ? " "+currentItem[4] : "";
			
			currentPinyin = currentItem[0];
			currentPinyin = add_missing_neutral_tones (currentPinyin);

			pinyinText = currentItem[1]
			characterText = currentItem[2];
			translationText = currentItem[3];
			lessonText = currentItem[4];
			exampleURL = currentItem[currentItem.length - 1];
		} else {
			if(sgc3_settings.shuffleLists) currentWordlist.shuffle();
			currentPinyin = "";
			currentItem = [];
		};
		// This cannot be the recorded Pinyin, therefor, clear all recorded data
		if (currentPinyin == "" || currentPinyin != sessionStorage.lastPinyin) clearRecordedData ();
		sessionStorage.lastPinyin = currentPinyin;

		document.getElementById('Pinyin').style.display = sgc3_settings.displayPinyin ? "inline" : "none";
		document.getElementById('Pinyin').style.color = "black";
		document.getElementById('Pinyin').textContent = sgc3_settings.displayNumbers ? currentPinyin : pinyinText;
		
		document.getElementById('Character').style.display = sgc3_settings.displayChar ? "inline" : "none";
		document.getElementById('Character').style.color = "black";
		document.getElementById('Character').textContent = characterText;
		
		document.getElementById('Translation').style.display = sgc3_settings.displayTrans ? "inline" : "none";
		document.getElementById('Translation').style.color = "black";
		document.getElementById('Translation').textContent = lessonText != "-" ? translationText + " ["+lessonText+"]": translationText;
		
		document.getElementById('Translation').style.fontSize = "6vmin";
		if (document.getElementById('Translation').textContent.length > 50) {
			document.getElementById('Translation').style.fontSize = "3.5vmin";
		} else if (document.getElementById('Translation').textContent.length > 30) {
			document.getElementById('Translation').style.fontSize = "4.5vmin";
		};
		
		document.getElementById("ResultString").textContent = "";
		document.getElementById("ResultString").style.color = "green";
		document.getElementById("FeedbackString").textContent = "";
		document.getElementById("FeedbackString").style.color = "green";
			
		// Plot tones and set recording time (Watch out for text appending: "3" + 0 can become "30")
		currentRecordingTime = Number(sgc3_settings.recSecs) + Number(1.0*Math.ceil((numSyllables(currentPinyin) - 2)/2));
		
		// Set progress bars
		var fillFraction = currentWord / (currentWordlist.length - 1);
		setProgressBar ("LeftProgress", -1*fillFraction);
		setProgressBar ("RightProgress", fillFraction);
		
		
		//Get tone contour
		initializeDrawingParam ("TonePlot");
		draw_example_pinyin ("TonePlot", currentPinyin);

		// Draw current sound
		// First, check whether there is a recorded sound stored (catch an invalid call to the "Audio" database)
		if(sgc3_settings.saveAudio && sgc3_settings.audioDatabaseName != "Audio") {
			var lesson = (lessonText != "-") ? " "+lessonText : "";
			getCurrentAudioWindow (sgc3_settings.currentCollection, sgc3_settings.wordList+lesson, currentPinyin+".wav");
		} else {
			processRecordedSound ()
		};
	};
	
	function write_WordlistName () {
		document.getElementById('WordlistString').textContent = sgc3_settings.wordList;
		// Always reset the selection
		selectWordlist.selectedIndex = 1;	
	};
	
	// Create the list with wordlists
	add_wordlist_names_to_select();
	
	sgc3_settings.wordList = (sgc3_settings.wordList) ? sgc3_settings.wordList : "20 basic tone combinations";
	get_wordlist (sgc3_settings.wordList);
	if(sgc3_settings.shuffleLists) currentWordlist.shuffle();
	var currentWord = 0;
	var currentItem = currentWordlist[currentWord];
	var currentPinyin = currentItem[0];
	var currentCharacter = currentItem[1];
	var currentString = currentItem[0] + " " + currentItem[1] + " " + currentItem[2];
	var currentLesson = "";
	write_CurrentString ();
		
	// Other parameters
	var mediaStream;
	var mediaConstraints = { audio: true, video: false };
	var errorCallback = function(err){console.log("Error: " + err.name);};
	
	// Reveal hidden display text
	displayText.onclick = function () {
		document.getElementById('Pinyin').style.display = "inline";
		if(!sgc3_settings.displayPinyin) document.getElementById('Pinyin').style.color = "red";
		document.getElementById('Character').style.display = "inline";
		if(!sgc3_settings.displayChar) document.getElementById('Character').style.color = "red";
		document.getElementById('Translation').style.display = "inline";
		if(!sgc3_settings.displayTrans) document.getElementById('Translation').style.color = "red";
	};
	
	// Settings button
	settingsButton.onclick = function () {
		if (localStorage.sgc3_settingsWindow && settingsWindow) {
			settingsWindow.focus();
		} else {
			if (settingsWindow) settingsWindow.close();
			settingsWindow = window.open('SpeakGoodChinese3_Settings.xml', '_blank');
			localStorage.sgc3_settingsWindow = JSON.stringify(true);
		}
	};
	
	// Play example 
	function meSpeakExample (pinyin ) {
			meSpeak.loadConfig("mespeak/mespeak_config.json"); 
			meSpeak.loadVoice('mespeak/voices/zh.json'); 
			meSpeak.speak(pinyin, {speed: sgc3_settings.ttsSpeed, variant: sgc3_settings.ttsVariant});	
	};
	
	function speakExample (voice, text, pinyin) {
		if (window.speechSynthesis) {
		    var msg = new SpeechSynthesisUtterance();
		    msg.onerror = function (event) {
				speechSynthesis.cancel();
				meSpeakExample (pinyin); 
			};
		    msg.voice = voice;
		    msg.rate = 0.7;
		    msg.text = text;
			speechSynthesis.speak(msg);
		} else {
			meSpeakExample (pinyin); 
		};
	};
	
	example.onclick = function() {
		if(! sgc3_settings.synthesis_eSpeak) {
			getAndPlayExample (sgc3_settings.wordList, currentPinyin, playBlob, generateExample);
		} else {
			meSpeakExample (currentPinyin);
		};
	};
	
	function playBlob (blob) {
		var exampleElement = document.getElementById('ExampleAudio');
		exampleElement.src = URL.createObjectURL(blob);
		exampleElement.play();
	};
	
	function generateExample () {
		var voice = getTTSvoice();
		if (exampleURL && exampleURL != "-") {
			exampleElement.src = exampleURL;
			exampleElement.onerror = function (event) {
			    currentText = currentWordlist[currentWord][2];
			    speakExample (voice, currentText, currentPinyin)
			};
			exampleElement.play();
		} else if (voiceZH_CN >= 0) {
		    currentText = currentWordlist[currentWord][2];
		    speakExample (voice, currentText, currentPinyin)
		} else {
			meSpeakExample (currentPinyin);
		};
	};

	// Previous word 
	previous.onclick = function() {
		--currentWord;
		while(! itemIsActive(currentWord))--currentWord;
 		if( currentWord < 0 ) {
			currentWord = currentWordlist.length;
			// Make sure the current word is indeed active
			while (currentWord > -1 && ! itemIsActive (currentWord)) --currentWord;		
		};
		write_CurrentString();
	};

	// Next word 
	next.onclick = function() {
		++currentWord;		
		while(! itemIsActive(currentWord))++currentWord;
		if(currentWord > currentWordlist.length) {
			currentWord = 0;
			// Make sure the current word is indeed active
			while (currentWord < currentWordlist.length && ! itemIsActive (currentWord)) ++currentWord;
		};
		write_CurrentString();
	};

	// Previous wordlist
	prevWordlist.onclick = function() {
		--wordlistNumber;
 		if( wordlistNumber < 0 ) {
			wordlistNumber = wordlists.length - 1;
		};
		sgc3_settings.wordList = wordlists[wordlistNumber][0];
		get_wordlist (sgc3_settings.wordList);
		if (sgc3_settings.shuffleLists) currentWordlist.shuffle();
		currentWord = 0;
		
		write_CurrentString();
		store_SGC3_settings ();
	};

	// Next wordlist
	nextWordlist.onclick = function() {
		++wordlistNumber;
 		if( wordlistNumber >= wordlists.length ) {
			wordlistNumber = 0;
		};
		sgc3_settings.wordList = wordlists[wordlistNumber][0];
		get_wordlist (sgc3_settings.wordList);
		if (sgc3_settings.shuffleLists) currentWordlist.shuffle();
		currentWord = 0;
		
		write_CurrentString();
		store_SGC3_settings ();
	};
	
	// select wordlist by name
	selectWordlist.onchange = function() {
		if (selectWordlist.selectedIndex > 1) {
			sgc3_settings.wordList = selectWordlist.options[selectWordlist.selectedIndex].value;
			get_wordlist (sgc3_settings.wordList);
			if (sgc3_settings.shuffleLists) currentWordlist.shuffle();
			currentWord = 0;
			
			write_CurrentString();
			store_SGC3_settings ();
		} else if (selectWordlist.selectedIndex == 0) {
			// Always reset the selection
			selectWordlist.selectedIndex = 1;
			// Open Wordlist page
			selectWordsWindow = window.open('SpeakGoodChinese3_SelectWords.xml', '_blank');
		};
	};
		
	function gradePrompt() {
		var promptText = mainpage_tables[sgc3_settings.language]["GRADE"][1];
		var currentGrade = "";
		if(performanceRecord && performanceRecord [currentLesson] && performanceRecord [currentLesson][currentPinyin].Grade >=0) {
			currentGrade = performanceRecord [currentLesson][currentPinyin].Grade + "";
		};
		var grade = prompt(promptText, currentGrade);
		if (sgc3_settings.saveAudio & grade != "" && grade >= 0 && grade <= 10 ) setGRADE(currentPinyin, grade);
		return void(0);
	};


	// When the call to getUserMEdia is susccessfull
	var successCallback = function(mediaStream){
		
		if(!mediaStream){ 
			console.log("No media stream: " + mediaStream);
		}
		
	    record.disabled = false;
	    record.style.color = "red";
		
		var recordRTC = RecordRTC(mediaStream, {
			type: "audio",
			// Pick the best available recorder at runtime:
			//   Chrome/Edge: MediaStreamRecorder + audio/webm
			//   Safari:      MediaStreamRecorder + audio/mp4
			//   Fallback:    StereoAudioRecorder + audio/wav
			recorderType: (function() {
				if (typeof MediaRecorder !== "undefined" && MediaRecorder.isTypeSupported("audio/webm")) return MediaStreamRecorder;
				if (typeof MediaRecorder !== "undefined" && MediaRecorder.isTypeSupported("audio/mp4"))  return MediaStreamRecorder;
				return StereoAudioRecorder;
			})(),
			mimeType: (function() {
				if (typeof MediaRecorder !== "undefined" && MediaRecorder.isTypeSupported("audio/webm")) return "audio/webm";
				if (typeof MediaRecorder !== "undefined" && MediaRecorder.isTypeSupported("audio/mp4"))  return "audio/mp4";
				return "audio/wav";
			})()
		});
		
		clearRecordedData = function () {
			play.disabled = true;
			play.style.color = "gray";
			recordRTC.clearRecordedData();
			clearRecording ();
		};
		
		// Play recorded sound
		play.onclick = function() {
			play_soundArray (currentAudioWindow, recordedSampleRate, 0, 0);
		};
		
		// Stop
		stopRecording = function() {
			recordRTC.stopRecording(function(audioURL) { 
				recordingLight.style.color = "gray";
				recordedBlobURL = audioURL;
				recordedBlob = recordRTC.getBlob();
				// Do things with Blob!!!
				processAudio (recordedBlob);
			});
		    play.disabled = false;
		    record.disabled = false;
		    record.style.color = "red";
		    play.style.color = "red";
		    recordingLight.style.color = "gray";
		}
		
		// onClick Start
		record.onclick = function() {
			clearRecordedData ();
			recordRTC.startRecording();
		    play.disabled = true;
		    record.disabled = true;
		    record.style.color = "gray";
		    play.style.color = "gray";
			recordingLight.style.top = "5%";
			recordingLight.style.left = "5%";
			recordingLight.style.fontSize = "15vmin";
		    recordingLight.style.color = "red";
		    
		    // Set Timeout for stop
		    setTimeout(stopRecording, currentRecordingTime * 1000);
		}
	
	};
	
	if (navigator.mediaDevices.getUserMedia) {
		navigator.mediaDevices.getUserMedia(mediaConstraints).then(successCallback).catch(errorCallback);
	} else {
		navigator.webkitGetUserMedia(mediaConstraints, successCallback, errorCallback);
	};

	// Initialize Audio storage
	load_SGC3_settings ();
	initializeDataStorage (sgc3_settings.currentCollection);
	
	// Read remote lists
	var url = window.location.href;
	url = url.replace(/[^\/]+$/, "wordlists/");
	readAllRemoteWordlists (url);
	
	//]]>	
	</script>
</body>
</html>
