diff options
Diffstat (limited to 'scripts/gui')
-rw-r--r-- | scripts/gui/chat.js | 306 | ||||
-rw-r--r-- | scripts/gui/input.js | 566 | ||||
-rw-r--r-- | scripts/gui/table.js | 278 |
3 files changed, 575 insertions, 575 deletions
diff --git a/scripts/gui/chat.js b/scripts/gui/chat.js index dda541e..f3b0975 100644 --- a/scripts/gui/chat.js +++ b/scripts/gui/chat.js @@ -1,102 +1,102 @@ 'use strict'; class Chat { - constructor(e, soc) - { - this.chats = []; - this.root = e; + constructor(e, soc) + { + this.chats = []; + this.root = e; this.socket = soc; - e.getElementsByClassName("toggle-chat")[0].onclick = this.toggle.bind(this); + e.getElementsByClassName("toggle-chat")[0].onclick = this.toggle.bind(this); let cin = e.getElementsByClassName("chat-input")[0]; this.chatInput = cin.children[0]; cin.children[0].addEventListener("keydown", this.checkEnter.bind(this)); cin.children[1].addEventListener("click", this.sendMessage.bind(this)); - } - - getChannel (name) - { - for(let i in this.chats) - { - if (this.chats[i].name == name) - { - return this.chats[i]; - } - } - - return null; - } - - isActive (name) - { - for(let i in this.chats) - { - if (this.chats[i].name == name) - { - if(this.chats[i].btn.getAttribute("active") == "true") - return true; - return false; - } - } - - return false; - } - - addChannel (name, follow = true) - { - if(this.getChannel(name) != null) - return; - - let d = document.createElement("div"); - let b = document.createElement("button"); - - this.root.getElementsByClassName("chat-select")[0].appendChild(b); - - b.setAttribute("active", false); - - b.onclick = this.switchChannel.bind(this, name); - - b.innerText = name; - - d.className = "chat-text"; - - this.chats.push({name: name, e: d, btn: b}); - - if(follow) - this.switchChannel(name) - } - - getActiveChannel () - { - for(let i in this.chats) - { - if (this.chats[i].btn.getAttribute("active") == "true") - { - return this.chats[i]; - } - } - - return null; - } - - switchChannel (name) - { - let c = this.getChannel(name); - - if(c == null) - return; - - if(this.getActiveChannel() != null) - this.getActiveChannel().btn.setAttribute("active", false); - - c.btn.setAttribute("active", true); - var ct = this.root.getElementsByClassName("chat-text")[0]; - ct.replaceWith(c.e); - - c.e.scroll({ - top: c.e.scrollTopMax - }); - } + } + + getChannel (name) + { + for(let i in this.chats) + { + if (this.chats[i].name == name) + { + return this.chats[i]; + } + } + + return null; + } + + isActive (name) + { + for(let i in this.chats) + { + if (this.chats[i].name == name) + { + if(this.chats[i].btn.getAttribute("active") == "true") + return true; + return false; + } + } + + return false; + } + + addChannel (name, follow = true) + { + if(this.getChannel(name) != null) + return; + + let d = document.createElement("div"); + let b = document.createElement("button"); + + this.root.getElementsByClassName("chat-select")[0].appendChild(b); + + b.setAttribute("active", false); + + b.onclick = this.switchChannel.bind(this, name); + + b.innerText = name; + + d.className = "chat-text"; + + this.chats.push({name: name, e: d, btn: b}); + + if(follow) + this.switchChannel(name) + } + + getActiveChannel () + { + for(let i in this.chats) + { + if (this.chats[i].btn.getAttribute("active") == "true") + { + return this.chats[i]; + } + } + + return null; + } + + switchChannel (name) + { + let c = this.getChannel(name); + + if(c == null) + return; + + if(this.getActiveChannel() != null) + this.getActiveChannel().btn.setAttribute("active", false); + + c.btn.setAttribute("active", true); + var ct = this.root.getElementsByClassName("chat-text")[0]; + ct.replaceWith(c.e); + + c.e.scroll({ + top: c.e.scrollTopMax + }); + } checkEnter(e) { @@ -113,67 +113,67 @@ class Chat { } - recieveMessage (channel, msg) - { - let c = this.getChannel(channel); - - if(c == null) - return; - - let autoscroll = c.e.scrollTop == c.e.scrollTopMax; - - let csp = document.createElement("span") - let tsp = document.createElement("span"); - - if(msg.server === true){ - csp.style.color = "white"; - csp.style.backgroundColor = "black"; - csp.innerText = "[SERVER]"; - tsp.innerText = " " + msg.text; - } else { - csp.style.color = msg.color; - csp.innerText = msg.user + ": "; - tsp.innerText = msg.text; - } - - let d = document.createElement("div"); - d.appendChild(csp); - d.appendChild(tsp); - - c.e.appendChild(d); - - if(autoscroll) - c.e.scroll({top: c.e.scrollTopMax}); - } - - clearChannel (name) - { - let c = this.getChannel(name); - if(c == null) - return; - - while(c.e.firstElementChild != null) - c.e.firstElementChild.remove(); - } - - deleteChannel (name) - { - let c = this.getChannel(name); - if(c == null) - return; - - while(c.e.firstElementChild != null) - c.e.firstElementChild.remove(); - - c.btn.remove(); - - this.chats.splice(this.chats.indexOf(c), 1); - } - - toggle () { - if(this.root.getAttribute("show") != "true") - this.root.setAttribute("show", "true"); - else - this.root.setAttribute("show", "false"); - } + recieveMessage (channel, msg) + { + let c = this.getChannel(channel); + + if(c == null) + return; + + let autoscroll = c.e.scrollTop == c.e.scrollTopMax; + + let csp = document.createElement("span") + let tsp = document.createElement("span"); + + if(msg.server === true){ + csp.style.color = "white"; + csp.style.backgroundColor = "black"; + csp.innerText = "[SERVER]"; + tsp.innerText = " " + msg.text; + } else { + csp.style.color = msg.color; + csp.innerText = msg.user + ": "; + tsp.innerText = msg.text; + } + + let d = document.createElement("div"); + d.appendChild(csp); + d.appendChild(tsp); + + c.e.appendChild(d); + + if(autoscroll) + c.e.scroll({top: c.e.scrollTopMax}); + } + + clearChannel (name) + { + let c = this.getChannel(name); + if(c == null) + return; + + while(c.e.firstElementChild != null) + c.e.firstElementChild.remove(); + } + + deleteChannel (name) + { + let c = this.getChannel(name); + if(c == null) + return; + + while(c.e.firstElementChild != null) + c.e.firstElementChild.remove(); + + c.btn.remove(); + + this.chats.splice(this.chats.indexOf(c), 1); + } + + toggle () { + if(this.root.getAttribute("show") != "true") + this.root.setAttribute("show", "true"); + else + this.root.setAttribute("show", "false"); + } } diff --git a/scripts/gui/input.js b/scripts/gui/input.js index a44784b..ddaa4a3 100644 --- a/scripts/gui/input.js +++ b/scripts/gui/input.js @@ -2,239 +2,239 @@ //Mostly fixed now class MakeInput { - static createInput(type = "text", wrap = false, getset = true) - { - var el = document.createElement("input"); - el.setAttribute("type", type); - - if(wrap) - { - return this.wrapInputs(type, el); - } - - if(getset) { - el.getValue = function () { - return this.value; - } - - el.setValue = function(value) { - this.value = value - } - } - - return el; - } - - // Function deprecated, finding another way to do this - static inputLabel(text, id) - { - var el = document.createElement("label"); - el.innerText = text; - if(typeof id == "string") - el.setAttribute("for", id); - return el; - } - - static colorInput (value) { - var el = MakeInput.createInput("color", true); - el.setValue(value); - return el; - } - - static textInput (value, placeholder) - { - var el = MakeInput.createInput("text"); - el.setAttribute("placeholder", placeholder); - el.value = value; - return el; - } - - static numberInput (value) - { - var el = MakeInput.createInput("number"); - el.value = value; - return el; - } - - static fileInput (accepts = "", multiple = false) { - var el = MakeInput.createInput("file", true, false); - - let e = el.getElement(); - e.setAttribute("accepts", accepts); - e.multiple = multiple; - el.getValue = function() { - return e.files; - } - - el.setAttribute("data-files", "Choose a file"); - - el.firstElementChild.onchange = function () { - let text = ""; - switch (this.files.length) { - case 0: - text = "Choose a file"; - break; - case 1: - text = "File: " + this.files[0].name; - break; - default: - text = "Files: " + this.files[0].name + "..."; - break; - } - el.setAttribute("data-files", text); - } - - return el; - } - - static checkboxInput (value = false) { - var el = MakeInput.createInput("checkbox", false, false); - - el.getValue = function() { - return el.checked; - } - - el.setValue = function(check) { - el.checked = check; - } - - el.setValue(value); - - return el; - } - - static radio (value, group, checked = false) { - var el = MakeInput.createInput("radio", false, false); - el.setAttribute("name", group); - el.setAttribute("value", value); - if(checked) - el.checked = true; - return el; - } - - static radioInput (values, names, group, prompt = "Select One", select = 0) { - - let toWrap = []; - - for(let i = 0; i < values.length; i++) { - toWrap.push(MakeInput.inputLabel(names[i])); - if(i == select) - toWrap.push(MakeInput.radio(values[i], group, true)); - else - toWrap.push(MakeInput.radio(values[i], group, false)); - toWrap.push(document.createElement("br")); - } - - var wrapper = MakeInput.wrapInputs("radio", ...toWrap); - - wrapper.setAttribute("data-prompt", prompt); - - wrapper.getValue = function() { - for(let i = 0; i < this.children.length; i++){ - if(this.children[i].checked) - return this.children[i].value; - } - }; - - wrapper.setValue = function(value) { - for(let i = 0; i < this.children.length; i++){ - if(this.children[i].value == value){ - this.children[i].checked = true; - return; - } - } - }; - - return wrapper; - } - - static wrapInputs (type, ...el) { - - var wrapper = document.createElement("div"); - wrapper.className = "input-container"; - wrapper.setAttribute("type", type); - - for(let i = 0; i < el.length; i++) - { - wrapper.appendChild(el[i]); - } - - if(el.length == 1) - { - wrapper.getValue = function () {return el[0].value;} - - wrapper.setValue = function(value) {el[0].value = value;} - - wrapper.onclick = el[0].click.bind(el[0]); - - wrapper.getElement = function(){return el[0];} - } - - return wrapper; - } - - static selectOption (value, text, index, selected) { - var so = document.createElement("div"); - so.innerText = text; - so.selectValue = value; - so.selectIndex = index; - so.addEventListener("mousedown", MakeInput.selOption.bind(null, so)); - - if(selected === true) - so.setAttribute("selected", true); - - return so - } - - static selectInput (values, names, select = 0) { - var se = document.createElement("div"); - se.className = "input-select"; - se.setAttribute("tabindex", 0); - se.setAttribute("selected", select); - - for(let i in names) - { - se.appendChild(MakeInput.selectOption(values[i], names[i], i, i == select)); - } - - var wrapper = MakeInput.wrapInputs("select", se); - wrapper.getValue = MakeInput.selValue.bind(null, se); + static createInput(type = "text", wrap = false, getset = true) + { + var el = document.createElement("input"); + el.setAttribute("type", type); + + if(wrap) + { + return this.wrapInputs(type, el); + } + + if(getset) { + el.getValue = function () { + return this.value; + } + + el.setValue = function(value) { + this.value = value + } + } + + return el; + } + + // Function deprecated, finding another way to do this + static inputLabel(text, id) + { + var el = document.createElement("label"); + el.innerText = text; + if(typeof id == "string") + el.setAttribute("for", id); + return el; + } + + static colorInput (value) { + var el = MakeInput.createInput("color", true); + el.setValue(value); + return el; + } + + static textInput (value, placeholder) + { + var el = MakeInput.createInput("text"); + el.setAttribute("placeholder", placeholder); + el.value = value; + return el; + } + + static numberInput (value) + { + var el = MakeInput.createInput("number"); + el.value = value; + return el; + } + + static fileInput (accepts = "", multiple = false) { + var el = MakeInput.createInput("file", true, false); + + let e = el.getElement(); + e.setAttribute("accepts", accepts); + e.multiple = multiple; + el.getValue = function() { + return e.files; + } + + el.setAttribute("data-files", "Choose a file"); + + el.firstElementChild.onchange = function () { + let text = ""; + switch (this.files.length) { + case 0: + text = "Choose a file"; + break; + case 1: + text = "File: " + this.files[0].name; + break; + default: + text = "Files: " + this.files[0].name + "..."; + break; + } + el.setAttribute("data-files", text); + } + + return el; + } + + static checkboxInput (value = false) { + var el = MakeInput.createInput("checkbox", false, false); + + el.getValue = function() { + return el.checked; + } + + el.setValue = function(check) { + el.checked = check; + } + + el.setValue(value); + + return el; + } + + static radio (value, group, checked = false) { + var el = MakeInput.createInput("radio", false, false); + el.setAttribute("name", group); + el.setAttribute("value", value); + if(checked) + el.checked = true; + return el; + } + + static radioInput (values, names, group, prompt = "Select One", select = 0) { + + let toWrap = []; + + for(let i = 0; i < values.length; i++) { + toWrap.push(MakeInput.inputLabel(names[i])); + if(i == select) + toWrap.push(MakeInput.radio(values[i], group, true)); + else + toWrap.push(MakeInput.radio(values[i], group, false)); + toWrap.push(document.createElement("br")); + } + + var wrapper = MakeInput.wrapInputs("radio", ...toWrap); + + wrapper.setAttribute("data-prompt", prompt); + + wrapper.getValue = function() { + for(let i = 0; i < this.children.length; i++){ + if(this.children[i].checked) + return this.children[i].value; + } + }; + + wrapper.setValue = function(value) { + for(let i = 0; i < this.children.length; i++){ + if(this.children[i].value == value){ + this.children[i].checked = true; + return; + } + } + }; + + return wrapper; + } + + static wrapInputs (type, ...el) { + + var wrapper = document.createElement("div"); + wrapper.className = "input-container"; + wrapper.setAttribute("type", type); + + for(let i = 0; i < el.length; i++) + { + wrapper.appendChild(el[i]); + } + + if(el.length == 1) + { + wrapper.getValue = function () {return el[0].value;} + + wrapper.setValue = function(value) {el[0].value = value;} + + wrapper.onclick = el[0].click.bind(el[0]); + + wrapper.getElement = function(){return el[0];} + } + + return wrapper; + } + + static selectOption (value, text, index, selected) { + var so = document.createElement("div"); + so.innerText = text; + so.selectValue = value; + so.selectIndex = index; + so.addEventListener("mousedown", MakeInput.selOption.bind(null, so)); + + if(selected === true) + so.setAttribute("selected", true); + + return so + } + + static selectInput (values, names, select = 0) { + var se = document.createElement("div"); + se.className = "input-select"; + se.setAttribute("tabindex", 0); + se.setAttribute("selected", select); + + for(let i in names) + { + se.appendChild(MakeInput.selectOption(values[i], names[i], i, i == select)); + } + + var wrapper = MakeInput.wrapInputs("select", se); + wrapper.getValue = MakeInput.selValue.bind(null, se); wrapper.getIndex = MakeInput.selIndex.bind(null, se); wrapper.addOption = MakeInput.selAdd.bind(se); wrapper.removeOption = MakeInput.selRem.bind(se); wrapper.setIndex = MakeInput.selSet.bind(se); - wrapper.setAttribute("tabindex", 0); + wrapper.setAttribute("tabindex", 0); + + return wrapper; + } - return wrapper; - } + static selValue (el) { + let sel = parseInt(el.getAttribute("selected")); + + if(typeof sel != "undefined") { + return el.children[sel].selectValue; + } - static selValue (el) { - let sel = parseInt(el.getAttribute("selected")); - - if(typeof sel != "undefined") { - return el.children[sel].selectValue; - } - - return ""; - } + return ""; + } static selIndex (el) { return parseInt(el.getAttribute("selected")); } - - static selOption (el, dispatch = true) { - let sn = el.selectIndex; - let psn = parseInt(el.parentElement.getAttribute("selected")); - - if(Number.isInteger(psn) && psn < el.parentElement.childElementCount) - el.parentElement.children[psn].setAttribute("selected", false); - - el.parentElement.setAttribute("selected", sn); - el.setAttribute("selected", true); + + static selOption (el, dispatch = true) { + let sn = el.selectIndex; + let psn = parseInt(el.parentElement.getAttribute("selected")); + + if(Number.isInteger(psn) && psn < el.parentElement.childElementCount) + el.parentElement.children[psn].setAttribute("selected", false); + + el.parentElement.setAttribute("selected", sn); + el.setAttribute("selected", true); if(dispatch) el.parentElement.parentElement.dispatchEvent(new InputEvent("change")); - } + } static selSet (index) { MakeInput.selOption(this.children[index], false); @@ -258,71 +258,71 @@ class MakeInput { return true; } - static titleWrap(el, title) { - var wrapper = document.createElement("div"); - wrapper.className = "input-title-wrapper"; - wrapper.setAttribute("type", el.getAttribute("type")); - wrapper.setAttribute("data-title", title); - - wrapper.appendChild(el); - - if(el.getAttribute("type") == "checkbox") - { - wrapper.onclick = el.click.bind(el); - } - - return wrapper; - } + static titleWrap(el, title) { + var wrapper = document.createElement("div"); + wrapper.className = "input-title-wrapper"; + wrapper.setAttribute("type", el.getAttribute("type")); + wrapper.setAttribute("data-title", title); + + wrapper.appendChild(el); + + if(el.getAttribute("type") == "checkbox") + { + wrapper.onclick = el.click.bind(el); + } + + return wrapper; + } } // Mostly fixed now class Settings { - constructor (template = {}) - { - this.settings = Settings.genSettings(template); - - this.wrappers = {}; - } - - static genSettings (template) - { - var out = {}; - - for(let key in template) - { - if(typeof MakeInput[template[key].type+"Input"] != null) - out[key] = {el: MakeInput[template[key].type+"Input"](...template[key].args), title: template[key].title}; - } - - return out; - } - - getSettings () - { - var out = {}; - - for(let key in this.settings) - out[key] = this.settings[key].el.getValue(); - - return out; - } - - putSettings (el) - { - this.cleanup(); - - this.wrappers = {}; - - for(let key in this.settings) { - this.wrappers[key] = MakeInput.titleWrap(this.settings[key].el, this.settings[key].title) - el.appendChild(this.wrappers[key]); - } - - } - - cleanup () - { - for(let key in this.wrappers) - this.wrappers[key].remove(); - } + constructor (template = {}) + { + this.settings = Settings.genSettings(template); + + this.wrappers = {}; + } + + static genSettings (template) + { + var out = {}; + + for(let key in template) + { + if(typeof MakeInput[template[key].type+"Input"] != null) + out[key] = {el: MakeInput[template[key].type+"Input"](...template[key].args), title: template[key].title}; + } + + return out; + } + + getSettings () + { + var out = {}; + + for(let key in this.settings) + out[key] = this.settings[key].el.getValue(); + + return out; + } + + putSettings (el) + { + this.cleanup(); + + this.wrappers = {}; + + for(let key in this.settings) { + this.wrappers[key] = MakeInput.titleWrap(this.settings[key].el, this.settings[key].title) + el.appendChild(this.wrappers[key]); + } + + } + + cleanup () + { + for(let key in this.wrappers) + this.wrappers[key].remove(); + } } diff --git a/scripts/gui/table.js b/scripts/gui/table.js index 9aac2ae..e242ac6 100644 --- a/scripts/gui/table.js +++ b/scripts/gui/table.js @@ -1,143 +1,143 @@ 'use strict'; // Table represents and manages the actual game. It accepts inputs from the server and tries to query the server when the player makes a move. class Table{ - constructor(e, drag, socket) { - this.root = e; - this.drag = drag; - - drag.addEventListener("dragstart", (e) => {console.log(e)}); - drag.addEventListener("dragstop", this.dragMsg.bind(this)); - - this.socket = socket; - - this.decks = []; - } - - openTable () - { - let state = this.root.getAttribute("state") - if((state == "close" || state == "closed") && state != "") { - this.root.setAttribute("state", "closed"); - setTimeout(this.root.setAttribute.bind(this.root), 50, "state", "open"); - } - } - - closeTable () - { - let state = this.root.getAttribute("state") - if(state != "close" && state != "closed") { - this.root.setAttribute("state", ""); - setTimeout(this.root.setAttribute.bind(this.root), 50, "state", "close"); - } - } - - handleClose () - { - this.reset(); - } - - reset () - { - while(this.root.firstElementChild != null) - this.root.firstElementChild.remove(); - - this.decks = []; - - this.closeTable(); - this.drag.stopDraggingAll(); - } - - /* Deck and card functions */ - newDeck(id, options) - { - var d = new Deck(id, options); - this.decks.push(d); - this.root.appendChild(d.e); - } - - newCard(id, data, deck = 0) - { - var c = new Card(id, data); - this.decks[deck].appendCard(c); - this.drag.addTarget(c.e); - } - - checkDeck(x, y) - { - for(let d of this.decks) - { - if(d.isInside(x, y)) - return d; - } - return null; - } - - checkCard (el) - { - for(let d of this.decks) - { - let c = d.checkCard(el); - if(c !== null) - return c; - } - return null; - } - - moveCard(card, newDeck, index = -1) - { - for(let d of this.decks) - { - if (d.removeCardByID(card.getID()) !== null) - break; - } - card.resetPos(); - - if(index < 0) - newDeck.appendCard(card); - else - newDeck.addCardAt(card, index); - } - - moveByID(cardID, deckID, index = -1) - { - let card, deck; - for(let d of this.decks) - { - let c = d.hasCard(cardID) - if(c !== null) - card = c; - - if(d.getID() == deckID) - deck = d; - } - - this.moveCard(card, deck, index); - } - - checkMove(cardID, deckID, index = -1) - { - this.socket.send("game", {type: "move", card: cardID, deck: deckID, pos: index}); - } - - dragCheck(cap) - { - console.log(cap); - } - - dragMsg (event) - { - if(event.drag.length < 1) - return; - - var c = this.checkCard(event.drag[0].e); - var d = this.checkDeck(event.x, event.y); - - if(c !== null) - { - if(d !== null) - this.checkMove(c.getID(), d.getID()); - else - c.resetPos(); - } - } + constructor(e, drag, socket) { + this.root = e; + this.drag = drag; + + drag.addEventListener("dragstart", (e) => {console.log(e)}); + drag.addEventListener("dragstop", this.dragMsg.bind(this)); + + this.socket = socket; + + this.decks = []; + } + + openTable () + { + let state = this.root.getAttribute("state") + if((state == "close" || state == "closed") && state != "") { + this.root.setAttribute("state", "closed"); + setTimeout(this.root.setAttribute.bind(this.root), 50, "state", "open"); + } + } + + closeTable () + { + let state = this.root.getAttribute("state") + if(state != "close" && state != "closed") { + this.root.setAttribute("state", ""); + setTimeout(this.root.setAttribute.bind(this.root), 50, "state", "close"); + } + } + + handleClose () + { + this.reset(); + } + + reset () + { + while(this.root.firstElementChild != null) + this.root.firstElementChild.remove(); + + this.decks = []; + + this.closeTable(); + this.drag.stopDraggingAll(); + } + + /* Deck and card functions */ + newDeck(id, options) + { + var d = new Deck(id, options); + this.decks.push(d); + this.root.appendChild(d.e); + } + + newCard(id, data, deck = 0) + { + var c = new Card(id, data); + this.decks[deck].appendCard(c); + this.drag.addTarget(c.e); + } + + checkDeck(x, y) + { + for(let d of this.decks) + { + if(d.isInside(x, y)) + return d; + } + return null; + } + + checkCard (el) + { + for(let d of this.decks) + { + let c = d.checkCard(el); + if(c !== null) + return c; + } + return null; + } + + moveCard(card, newDeck, index = -1) + { + for(let d of this.decks) + { + if (d.removeCardByID(card.getID()) !== null) + break; + } + card.resetPos(); + + if(index < 0) + newDeck.appendCard(card); + else + newDeck.addCardAt(card, index); + } + + moveByID(cardID, deckID, index = -1) + { + let card, deck; + for(let d of this.decks) + { + let c = d.hasCard(cardID) + if(c !== null) + card = c; + + if(d.getID() == deckID) + deck = d; + } + + this.moveCard(card, deck, index); + } + + checkMove(cardID, deckID, index = -1) + { + this.socket.send("game", {type: "move", card: cardID, deck: deckID, pos: index}); + } + + dragCheck(cap) + { + console.log(cap); + } + + dragMsg (event) + { + if(event.drag.length < 1) + return; + + var c = this.checkCard(event.drag[0].e); + var d = this.checkDeck(event.x, event.y); + + if(c !== null) + { + if(d !== null) + this.checkMove(c.getID(), d.getID()); + else + c.resetPos(); + } + } } |