e-対戦 [e-typing]

e-typingに対戦機能を追加したい

目前為 2023-07-30 提交的版本,檢視 最新版本

// ==UserScript==
// @name         e-対戦 [e-typing]
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  e-typingに対戦機能を追加したい
// @author       Toshi
// @match        https://www.e-typing.ne.jp/app/jsa_std*
// @exclude      https://www.e-typing.ne.jp/app/ad*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=e-typing.ne.jp
// @grant        none
// @license MIT
// @require      https://www.gstatic.com/firebasejs/7.2.1/firebase-app.js
// @require      https://www.gstatic.com/firebasejs/7.2.1/firebase-auth.js
// @require      https://www.gstatic.com/firebasejs/7.2.1/firebase-database.js





// ==/UserScript==

const firebaseConfig = {
	apiKey: "AIzaSyDsHiPII5dgN_AEGwOtMehyveucoF4Twvs",
	databaseURL: "https://e-typing-battle-default-rtdb.firebaseio.com"
};


class MyResult{

	constructor(){
		this.interval
	}


	sendResetResult(){
		let updates = {};

		//ユーザーネーム更新
		updates['/users/' + myID + '/result/' + '/score'] = 0;
		updates['/users/' + myID + '/result/' + '/time'] = 0;
		updates['/users/' + myID + '/result/' + '/typeCount'] = 0;
		updates['/users/' + myID + '/result/' + '/missCount'] = 0;
		updates['/users/' + myID + '/result/' + '/wpm'] = 0;
		updates['/users/' + myID + '/result/' + '/latency'] = 0;
		updates['/users/' + myID + '/result/' + '/rkpm'] = 0;

		firebase.database().ref().update(updates)
	}

	sendResult(){

		if(battleUserData.data){

			firebase.database().ref('users/' + battleUserData.data.key + '/result').once('value').then(battleUserResult => {
				const RESULT = battleUserResult.val()
				})

			firebase.database().ref('users/' + battleUserData.data.key + '/result').on('child_changed', myResult.onBattleResultDisplay);
		}

		const RESULT_DATA = document.getElementsByClassName("result_data")[0].firstElementChild.children

		const score = RESULT_DATA[0].getElementsByClassName("data")[0].textContent
		const time = RESULT_DATA[2].getElementsByClassName("data")[0].textContent
		const typeCount = RESULT_DATA[3].getElementsByClassName("data")[0].textContent
		const missCount = RESULT_DATA[4].getElementsByClassName("data")[0].textContent
		const wpm = RESULT_DATA[5].getElementsByClassName("data")[0].textContent
		const latency = RESULT_DATA[7].getElementsByClassName("data")[0].textContent
		const rkpm = RESULT_DATA[8].getElementsByClassName("data")[0].textContent


		let updates = {};

		//ユーザーネーム更新
		updates['/users/' + myID + '/result/' + '/score'] = score;
		updates['/users/' + myID + '/result/' + '/time'] = time;
		updates['/users/' + myID + '/result/' + '/typeCount'] = typeCount;
		updates['/users/' + myID + '/result/' + '/missCount'] = missCount;
		updates['/users/' + myID + '/result/' + '/wpm'] = wpm;
		updates['/users/' + myID + '/result/' + '/latency'] = latency;
		updates['/users/' + myID + '/result/' + '/rkpm'] = rkpm;

		firebase.database().ref().update(updates)

	}

	onBattleResultDisplay(snapshot){
		const uid = snapshot.ref_.path.pieces_[1];
		const Update_Info = snapshot.ref_.path.pieces_[3]
		const SnapShotValue = snapshot.val()

		switch(Update_Info){
			case "score":
				break;

			case "time":
				break;

			case "typeCount":
				break;

			case "missCount":
				break;

			case "wpm":
				break;

			case "latency":
				break;

			case "rkpm":
				break;
		}
	}

	reBuildResultAria(){
		document.getElementById("RTCGamePlayScene").style.marginTop = ''
		document.getElementById("comment").style.display = 'none'
		document.getElementById("result").querySelector('article').style.height = '392px'
	}


	checkResultDisplay(){
		const Result = document.getElementsByClassName("result_data")[0].firstElementChild.children[8].getElementsByClassName("data")[0]

		//リザルトが表示された
		if(Result){
			myResult.sendResult()
			myResult.reBuildResultAria()
			clearInterval(myResult.interval)
		}
	}



}
let myResult


class MyStatus{

	constructor(){
		this.lineInput = ''
		this.clearCount = 0

	}


	sendResetStatus(){
		let updates = {};

		//ユーザーネーム更新
		updates['/users/' + myID + '/status/' + '/lineInput'] = '';
		updates['/users/' + myID + '/status/' + '/clearCount'] = 0;


		firebase.database().ref().update(updates)
	}
}
let myStatus


class MyData {

	constructor(){
		this.prevState
		this.locationDateTimeStamp
		this.localDateTimeStamp
		this.myName
		myResult = new MyResult()
		myStatus = new MyStatus()
	}

	update(){
		var updates = {};
		this.myName = localStorage.getItem("battleName")

		//ユーザーネーム更新
		updates['/usersState/' + myID + '/name'] = this.myName;
		updates['/usersState/' + myID + '/state'] = this.prevState = "idle";

		firebase.database().ref().update(updates)
		myResult.sendResetResult()
		myStatus.sendResetStatus()
		document.getElementById("start_btn").style.display = 'block'
		document.getElementsByClassName("loading")[0].style.display = 'none'
	}

	updateTimeStamp(){
		const newDate = new Date().getTime()
		var updates = {};
		const deleteTimeStamp = myData.locationDateTimeStamp + (newDate - myData.locationDateTimeStamp)
		updates['/users/' + myID + '/deleteTimeStamp'] = deleteTimeStamp


		//30秒に一度、ルーム内のユーザーの存在をチェックする
		/* 		if(isEnter && !playing && new_Date - RoomUserAfkWriteClock >= 30000){
			RoomUserAfkWriteClock = new_Date
			roomUserTimeoutCheck(deleteTimeStamp)
		} */

		firebase.database().ref().update(updates);
	}


	startingClockTime(){

		/* 		if(roomID == null && !wholeRoom){
			addWholeRoomsUpdateEvent()
			setTimeout(()=> {document.getElementById("noRoomMes").textContent = "現在ルームが存在しません。";},700)
		} */

		//ユーザー確認用タイムスタンプを更新
		this.updateTimeStamp()
		setInterval(this.updateTimeStamp,5000)
	}

	async getLocationDate(){
		const resp = await fetch(window.location.href)

		//サーバー時刻のタイムスタンプ
		this.locationDateTimeStamp = await new Date(resp.headers.get("date")).getTime()
		//ローカル時刻タイムスタンプ
		this.localDateTimeStamp = new Date().getTime()

		//LocationDateTimeStamp + (new Date().getTime() - LocalDateTimeStamp)
		//サーバー時刻のタイムスタンプ + (現在のローカル時刻 - ローカル時刻タイムスタンプ)
		//上記の計算で環境の違いでズレない時刻を取得

		////////////////////////////////////////////////////////////////////

		//サーバー時刻取得後、現在ログインしていない部屋とユーザー情報を削除
		//deleteIdlePlayerAndRoom();
		return true
	}

}
let myData


let myID
class LoginFirebase {

	constructor(){


		firebase.initializeApp(firebaseConfig)
		this.roginAnon()
	}


	roginAnon(){

		firebase.auth().signInAnonymously().catch(function(error) {
			// Handle Errors here.
			var errorCode = error.code;
			var errorMessage = error.message;

			console.log(errorCode);
			console.log( errorMessage);
			alert("RealTimeCombatting:Firebaseのサインインに失敗しました。");
			return false;
			// ...
		});

		firebase.auth().onAuthStateChanged(function(user) {

			if (user) {
				// User is signed in.
				myID = "U"+user.uid
				console.log('!!!')

				var path = firebase.database().ref('users/' + myID);

				path.transaction(function(currentData) {
					//ユーザー情報を更新
					myData = new MyData()
					myData.update()
					myData.getLocationDate().then( () => myData.startingClockTime())
				});
			}
		});

	}
}

let loginFirebase = new LoginFirebase()





let typingAppModInterval
let createOptionInterval






const createOption = () => {
	const FUNC_VIEW = document.getElementById("func_view")

	//設定エリアが表示された
	if(FUNC_VIEW){
		setUpMenu(FUNC_VIEW)
		clearInterval(createOptionInterval)
	}
}



const typingAppMod = () => {

	const example_container = document.getElementById("example_container") //iframe内の要素を取得

	//タイピング画面に移動した。
	if(example_container){

		if(setUp.battleSwitch){
			battleArea = new BattleArea()
			keyJudge = new KeyJudge()
			keyJudge.addEvent()
			setMutationObserver = new SetMutationObserver()
		}






		clearInterval(typingAppModInterval)
		typingAppModInterval = null
	}

}


class SetMutationObserver {

	constructor(){
		this.set()
	}

	set(){
		var observer = new MutationObserver(function(){
			console.log('???')

			const RTC = document.getElementById("RTCGamePlayScene")
			if(RTC){
				myResult.interval = setInterval(myResult.checkResultDisplay,50)
			}
		});

		const elem = document.getElementById("app")

		const config = {
			childList: true//「子ノード(テキストノードも含む)」の変化
		};

		observer.observe(elem, config);
	}

}
let setMutationObserver


const createEventInTypingApp = (() => {

	typingAppModInterval = setInterval(typingAppMod , 50)
	createOptionInterval = setInterval(createOption , 100)

	/*
		//タイピング中にEscキーを押したらtypingAppModを実行
		window.addEventListener("keydown", event => {
			// document.getElementById("miss_type_screen") {タイピングワードが表示される要素}
			// document.getElementById("miss_type_screen") 要素が存在する場合のみ即時リトライを適用。(打ち切り時の結果画面等では無効化。)
			if(!typingAppModInterval && event.key == "Escape" && document.getElementById("exampleText") != null && document.getElementById("miss_type_screen") != null){
				typingAppModInterval = setInterval(typingAppMod , 50)
			}
			if(!typingAppModInterval && event.code == "KeyR" && document.getElementById("replay_btn") != null){
				typingAppModInterval = setInterval(typingAppMod , 50)
			}
		},true)

		//打ち切り時にやり直しボタン or ミスだけボタンをクリックしたらtypingAppModを実行
		window.addEventListener("click", event => {

			if(!typingAppModInterval && event.target.id == "replay_btn" || event.target.id == "miss_only_btn"){
				typingAppModInterval = setInterval(typingAppMod , 50)
			}
		},true)
*/

})()






class KeyJudge {

	constructor(){
		this.wordReload = false;
		this.clearLine = 0
	}

	addEvent(){
		this.Event = this.wait.bind(this)
		this.playEvent = this.startSpaceKey.bind(this)
		window.addEventListener("keydown",this.Event)
		window.addEventListener("keydown",this.playEvent)
	}

	removeEvent(){
		window.removeEventListener("keydown",this.playEvent)
	}

	wait(event){
		setTimeout(() => this.keyDown(event))
	}

	startSpaceKey(event){
		if(event.code == 'Space'){
			battleArea.updatePlay(null,'solo')
			this.removeEvent()
			document.getElementById('virtual_keyboard').style.display = 'block';
			document.getElementById('hands').style.display = 'block';
			document.getElementById('RTCGamePlayScene').style.display = 'none';

		}
	}

	judge(event , sentenceText){
		let result
		if(setUp.typingMode == "roma"){
			result = sentenceText.textContent.slice(-1).toLowerCase() == event.key ? true:false
		}else if(setUp.typingMode == "eng"){
			result = sentenceText.textContent.slice(-1).replace("␣", " ") == event.key ? true:false
		}else if(setUp.typingMode == "kana"){
			result = this.createKanaChar(event).includes(sentenceText.textContent.slice(-1))
		}
		return result;
	}

	keyDown(event){

		const sentenceText = document.getElementsByClassName("entered")[setUp.enteredClass]
		let key

		if(sentenceText){
			key = this.judge(event , sentenceText)
		}

		if(event.key == "Escape"){
			this.wordReload = false
		}

		if(!sentenceText && this.wordReload){
			this.sendWordData('')
			this.wordReload = true

			if(!sentenceText){
				this.wordReload = false
			}

		}else if(sentenceText && key){

			this.sendWordData(sentenceText.textContent)
			this.wordReload = true

			if(!sentenceText){
				this.wordReload = false
			}

		}
	}

	createKanaChar(event){
		let char = windows_keymap[event.code] ? windows_keymap[event.code] : kana_keymap[event.key];

		if(event.shiftKey){
			if(event.code == "KeyE"){char[0] = "ぃ";}
			if(event.code == "KeyZ"){char[0] = "っ";}
		}

		if(event.shiftKey && event.key === "0"){char = ["を"];}

		return char;
	}

	sendWordData(text) {

		var updates = {}
		updates['/users/' + myID + '/status/' + '/lineInput'] = text.substr( -24, 24 );

		if(!text){
			this.clearLine++
			updates['/users/' + myID + '/status/' + '/clearCount'] = this.clearLine

		}

		firebase.database().ref().update(updates)
	}

}
let keyJudge






class BattleArea {

	constructor(){
		battleUserData = new BattleUserData()
		this.updatePreStart()
		this.createArea()
	}

	searchPreStartPlayer(){

		firebase.database().ref('usersState/').once('value').then(users => {
			const USERS = users.val()
			const USERS_KEY = Object.keys(USERS)
			battleUserData.data = null

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

				if(USERS_KEY[i] != myID && USERS[USERS_KEY[i]].state == 'preStart'){
					battleUserData.data = {
						name:USERS[USERS_KEY[i]].name,
						key:USERS_KEY[i],
						mode:'roma'
					}
					this.createBattleTable()
					this.updatePlay(USERS_KEY[i])
					return
					break;
				}

			}

			if(!battleUserData.data){
				this.createBattleTable('wait')
			}
		})
	}

	createBattleTable(wait){

		if(!wait){
			this.addbattleStatusTable(battleUserData.data.name , battleUserData.data.key , battleUserData.data.mode)
			firebase.database().ref('users/' + battleUserData.data.key + '/status').on('child_changed', battleUserData.onUpdateUserStatus);
			this.updatePlay()
		}

		firebase.database().ref('usersState/').on('child_changed', battleUserData.onChangeUserState);

	}


	updatePreStart(){
		var updates = {}
		updates['/usersState/' + myID + '/state'] = myData.prevState = "preStart";
		firebase.database().ref().update(updates)
		this.searchPreStartPlayer()
	}

	displayReadyButton(){
		document.getElementById("l-ready-button").style.display = 'block'
		document.getElementById("ready-button").style.display = 'block'
	}

	updateReadyState(){
		var updates = {}
		updates['/usersState/' + myID + '/state'] = myData.prevState = "ready";
		updates['/users/' + myID + '/status/' + '/lineInput'] = '準備完了';
		firebase.database().ref().update(updates)
	}

	updatePlay(battleUserKey,solo){
		var updates = {}

		if(!solo){
			this.displayReadyButton()
			updates['/usersState/' + myID + '/state'] = myData.prevState = "play";
		}else{
			updates['/usersState/' + myID + '/state'] = myData.prevState = "soloPlay";
		}

		if(battleUserKey){
			updates['/usersState/' + battleUserKey + '/state'] = "play";
		}
		firebase.database().ref().update(updates)


	}

	createArea(){
		document.getElementById('virtual_keyboard').style.display = 'none';
		document.getElementById('hands').style.display = 'none';
		document.getElementById("ad_frame").style.display = 'none';

		document.getElementById('start_msg').insertAdjacentHTML("afterbegin" ,
`<div style="cursor: pointer; display: none;position: absolute;bottom: -23px;left: 28px;width: 130px;font-size: 1.1rem;" class="loading" id='ready-button'>準備完了</div>
<div style="cursor: pointer;display: none;position: absolute;bottom: -23px;width: 130px;right: 26px;font-size: 0.8rem;" class="loading" id='l-ready-button'>Lスタートで準備完了</div>`)

		document.getElementById("ready-button").addEventListener('click', event => {
			event.target.style.display = 'none'
			document.getElementById("l-ready-button").style.display = 'none'
			battleArea.updateReadyState()
		})

		document.getElementById("l-ready-button").addEventListener('click', event => {
			event.target.style.display = 'none'
			document.getElementById("ready-button").style.display = 'none'
			battleArea.updateReadyState()
		})



		document.getElementById('example_container').insertAdjacentHTML('afterend',`<div id="RTCGamePlayScene" style='margin-top:3rem;'></div>`)


	}



	addbattleStatusTable(userName,key,inputType){
		const INPUT_TYPE = inputType != 'kana' ? 'ローマ字' : 'かな'

		const TABLE = `<table class='user-table' rules="all" border="1"><tbody>
<tr id="${key}">
<td rowspan="2" class='user-name'>${userName}</td>
<td class="RTCLine" colspan="7"></td>
<td class="InputMode">${INPUT_TYPE}</td>
<td class="clear-line"><span class="clear-count">0</span>/15</td></tr></tbody></table>`

		document.getElementById("RTCGamePlayScene").insertAdjacentHTML('beforeend',TABLE)

	}
}
let battleArea



class BattleUserData{

	constructor(){
		this.data
	}


	onUpdateUserStatus(snapshot){
		const uid = snapshot.ref_.path.pieces_[1];
		const Update_Info = snapshot.ref_.path.pieces_[3]
		const SnapShotValue = snapshot.val()

		switch(Update_Info){
			case "clearCount":
				document.getElementById(uid).getElementsByClassName('clear-count')[0].textContent = SnapShotValue
				break;

			case "lineInput":
				if(SnapShotValue){
					document.getElementById(uid).getElementsByClassName('RTCLine')[0].textContent = SnapShotValue;
				}else{
					document.getElementById(uid).getElementsByClassName('RTCLine')[0].textContent = "";
				}
				break;
		}
	}

	onChangeUserState(snapshot){
		const uid = snapshot.ref_.path.pieces_[1];
		const Update_Info = snapshot.ref_.path.pieces_[3]
		const SnapShotValue = snapshot.val()

		if(battleUserData.data && uid == battleUserData.data.key){
			battleUserData.data.state = SnapShotValue.state;
		}

		if(uid != myID && myData.prevState == "preStart" && SnapShotValue.state == 'preStart'){

			battleUserData.data = {
				name:SnapShotValue.name,
				key:uid,
				mode:'roma',
				state:SnapShotValue.state
			}

			battleArea.addbattleStatusTable(battleUserData.data.name , battleUserData.data.key , battleUserData.data.mode)
			firebase.database().ref('users/' + uid + '/status').on('child_changed', battleUserData.onUpdateUserStatus);
			battleArea.updatePlay(uid)
		}

		if(battleUserData.data && (battleUserData.data.key == uid || myID == uid) && battleUserData.data.state == 'ready' && myData.prevState == "ready"){
			document.dispatchEvent( new KeyboardEvent("keydown",{keyCode:32}))
			keyJudge.removeEvent()
		}

		if(battleUserData.data && uid == battleUserData.data.key && battleUserData.data.state == 'soloPlay' || battleUserData.data.state == 'idle'){
			battleUserData.data = null
			battleArea.updatePreStart()
			document.getElementsByClassName("user-table")[0].remove()
		}
	}


}
let battleUserData




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////







const kana_keymap = {
	0: ["わ"],
	1: ["ぬ"],
	"!": ["ぬ"],
	2: ["ふ"],
	3: ["あ"],
	4: ["う"],
	5: ["え"],
	6: ["お"],
	7: ["や"],
	8: ["ゆ"],
	9: ["よ"],
	"-": ["ほ","-"],
	"q": ["た"],
	"Q": ["た"],
	"w": ["て"],
	"W": ["て"],
	"e": ["い"],
	"E": ["い"],
	"r": ["す"],
	"R": ["す"],
	"t": ["か"],
	"T": ["か"],
	"y": ["ん"],
	"Y": ["ん"],
	"u": ["な"],
	"U": ["な"],
	"i": ["に"],
	"I": ["に"],
	"o": ["ら"],
	"O": ["ら"],
	"p": ["せ"],
	"P": ["せ"],
	"a": ["ち"],
	"A": ["ち"],
	"s": ["と"],
	"S": ["と"],
	"d": ["し"],
	"D": ["し"],
	"f": ["は"],
	"F": ["は"],
	"g": ["き"],
	"G": ["き"],
	"h": ["く"],
	"H": ["く"],
	"j": ["ま"],
	"J": ["ま"],
	"k": ["の"],
	"K": ["の"],
	"l": ["り"],
	"L": ["り"],
	"z": ["つ"],
	"Z": ["つ"],
	"x": ["さ"],
	"X": ["さ"],
	"c": ["そ"],
	"C": ["そ"],
	"v": ["ひ"],
	"V": ["ひ"],
	"b": ["こ"],
	"B": ["こ"],
	"n": ["み"],
	"N": ["み"],
	"m": ["も"],
	"M": ["も"],
	",": ["ね",","],
	"<": ["、"],
	".": ["る","."],
	">": ["。"],
	"/": ["め","/"],
	"?": ["・"],
	"#": ["ぁ"],
	"$": ["ぅ"],
	"%": ["ぇ"],
	"'": ["ゃ","’","'"],
	"^": ["へ"],
	"~": ["へ"],
	"&": ["ぉ"],
	"(": ["ゅ"],
	")": ["ょ"],
	'|': ["ー"],
	"_": ["ろ"],
	"=": ["ほ"],
	"+": ["れ"],
	";": ["れ"],
	'"': ["ふ","”","“","\""],
	"@": ["゛"],
	'`': ["゛"],
	"[": ["゜"],
	']': ["む"],
	"{": ["「"],
	'}': ["」"],
	":": ["け"],
	"*": ["け"]
}

const windows_keymap = {
	'IntlYen': ["ー","¥","\\"],
	"IntlRo": ["ろ","¥","\\"],
	"Space": [" "],
	"Numpad1": [],
	"Numpad2": [],
	"Numpad3": [],
	"Numpad4": [],
	"Numpad5": [],
	"Numpad6": [],
	"Numpad7": [],
	"Numpad8": [],
	"Numpad9": [],
	"Numpad0": [],
	"NumpadDivide": [],
	"NumpadMultiply": [],
	"NumpadSubtract": [],
	"NumpadAdd": [],
	"NumpadDecimal": []
}

class SetUp {

	constructor(){

		this.typingMode = 'roma'
		this.enteredClass = 2
		this.battleSwitch = true

	}

	checkTypingMode(){

		if(location.href.match(/kana\.1/)){
			this.typingMode = "kana"
			this.enteredClass = 1
		}else if(location.href.match(/std\.2/) || location.href.match(/lstn\.4/)){
			this.typingMode = "eng"
			this.enteredClass = 1
		}else{
			this.typingMode = "roma"
			this.enteredClass = 2
		}

	}

}

const setUp = new SetUp()


function setUpMenu(FUNC_VIEW){

	const NAME = localStorage.getItem("battleName")
	setUp.battleSwitch = localStorage.getItem("battle-option") == "false" ? false : true;

	addCss()
	document.getElementById("start_btn").style.display = setUp.battleSwitch == false ? '' : 'none'
	document.getElementById("start_btn").insertAdjacentHTML('afterend',`<div class='loading'>対戦データベースに接続中</div>`)
	FUNC_VIEW.style.height = document.getElementById("func_view").clientHeight + 30 + "px"
	FUNC_VIEW.insertAdjacentHTML('beforeend' ,
`<div><div>
<label><small>対戦機能</small>
<input id="battle-option" type="checkbox" style="display:none;" ${setUp.battleSwitch == false ? "" : "checked"}>
<div id="sound-effect-btn" style="margin-left:4px;" class="switch_btn"><a class="on_btn btn show">ON</a>
<a class="off_btn btn" style="display:${setUp.battleSwitch == false ? "block" : ""};">OFF</a></div>
</label>
<input type="text" id="battle-name" placeholder="Name" value="${NAME ? NAME : 'Guest'}" maxlength="10" style="display:${setUp.battleSwitch == false ? "none" : "inline"}; position: absolute;width: 7rem;margin: 2px;right: 85px;">
</div></div>`)

	if(!NAME){
		localStorage.setItem("battleName" , 'Guest')
	}


	document.getElementById("battle-name").addEventListener("change", event => {
		localStorage.setItem("battleName" , event.target.value)
		myData.update()
	})

	document.getElementById("battle-option").addEventListener("change" , event => {
		localStorage.setItem("battle-option" , event.target.checked);

		if(event.target.checked){
			document.querySelector("#sound-effect-btn .off_btn").style.display = ""
			document.getElementById("battle-name").style.display = "inline"
			setUp.battleSwitch = true;
		}else{
			document.querySelector("#sound-effect-btn .off_btn").style.display = "block"
			document.getElementById("battle-name").style.display = "none"
			setUp.battleSwitch = false;
		}

	})
}


function addCss(){

	document.getElementById("app").insertAdjacentHTML('afterend',`<style>


.loading{
    color: #fff;
    font-size: 12px;
    font-weight: bold;
    background-color: #057fff;
    width: 160px;
    height: 45px;
    margin: 0 auto;
    text-align: center;
    line-height: 45px;
    overflow: hidden;
    border-radius: 3px;
}

.user-table{
width: 96%;
position: relative;
left: 0;
right: 0;
margin: auto;
}

.user-table tr{
font-weight:bold;
height: 3rem;
}

.user-name{
width:11%;
text-align: center;
}

.RTCLine{
max-width: 350px;
white-space: nowrap;
overflow:hidden;
width: 68%;
color:#ffd0a6;
font-size: 26px;
font-weight: normal;
}

.InputMode{
font-size: 0.9rem;
text-align: center;
}

.clear-line{
font-size: 1rem;
text-align: center;
}

#RTCGamePlayScene{
margin: 8px;
}
</style>`)

}