From c17123283ec460dce811b6eb233d3c735e50e0f6 Mon Sep 17 00:00:00 2001 From: nishith-hbf Date: Fri, 28 Oct 2022 00:10:21 +0530 Subject: [PATCH 1/9] Play against a tic tac toe AI, best outcome - Draw --- pointless-tic-tac-toe/index.html | 46 +++++ pointless-tic-tac-toe/script.js | 324 +++++++++++++++++++++++++++++++ pointless-tic-tac-toe/style.css | 104 ++++++++++ 3 files changed, 474 insertions(+) create mode 100644 pointless-tic-tac-toe/index.html create mode 100644 pointless-tic-tac-toe/script.js create mode 100644 pointless-tic-tac-toe/style.css diff --git a/pointless-tic-tac-toe/index.html b/pointless-tic-tac-toe/index.html new file mode 100644 index 00000000..248c2442 --- /dev/null +++ b/pointless-tic-tac-toe/index.html @@ -0,0 +1,46 @@ + + + + + + + Pointless + + + + + + + +
+ + vs + +
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/pointless-tic-tac-toe/script.js b/pointless-tic-tac-toe/script.js new file mode 100644 index 00000000..1244b6e5 --- /dev/null +++ b/pointless-tic-tac-toe/script.js @@ -0,0 +1,324 @@ +const grid_side = 3 +const PLAYER_X = 1 +const PLAYER_Y = -1 +var X_human = true +var O_human = false +const player_controller = (()=>{ + const notify =(player,states)=>{ + if(player==PLAYER_X){ + if(!X_human){ + //wait for 1 second + setTimeout(()=>{ + let move = agent.pickMove(states, PLAYER_X) + let pos = move['i']*3+move['j'] + cells[pos].select() + gameBoard.select(pos) + },250) + } + } + else{ + if(!O_human){ + //wait for 1 second + setTimeout(()=>{ + let move = agent.pickMove(states,player) + let pos = move['i']*3+move['j'] + cells[pos].select() + gameBoard.select(pos) + },500) + } + } + } + return {notify} +})() +const agent = (()=>{ + const pickMove = (states,player)=>{ + let bestMove + if(player == PLAYER_X){ + let bestScore = -Infinity + for(let i=0;ibestScore){ + bestScore = score + a = " "+i + b = " "+ j + bestMove = {i,j} + } + } + } + } + } + else{ + let bestScore = Infinity + for(let i=0;i{ + // console.log(""+states); + result = checkWinner(states) + if(result!=null){ + if(result == PLAYER_X) + return 100-depth + else if(result == PLAYER_Y) + return -100+depth + else return 0 + } + let bestScore; + if(isMaximising){ + bestScore = -Infinity + for(let i =0;i{ + // check rows + for(let i=0;i{ + let _winner + let _gameOver = false + let _state = new Array(3) + for(let i = 0; i < _state.length; i++){ + _state[i] = new Array(3).fill(0) + } + let _currPlayer = PLAYER_X + const isGameOver = ()=> _gameOver + const select = (num)=>{ + // console.log(num); + if(_currPlayer==PLAYER_X){ + _state[Math.floor(num/3)][num%3] = 1 + _currPlayer = PLAYER_Y + } + else{ + _state[Math.floor(num/3)][num%3] = -1 + _currPlayer = PLAYER_X + } + validateBoard() + if(!_gameOver) + player_controller.notify(_currPlayer,_state) + + } + const getChar = ()=>{ + if(_currPlayer==PLAYER_X) return 'X' + else return 'O' + } + + const validateBoard = ()=>{ + //check rows + for(let i = 0; i < _state.length; i++){ + if(_state[i][0] == _state[i][1] && _state[i][1] == _state[i][2] && _state[i][0] != 0){ + _winner = _state[i][0]==1?PLAYER_X:PLAYER_Y + console.log(_winner); + _gameOver = true + } + } + //check columns + for(let i = 0; i < _state.length; i++){ + if(_state[0][i] == _state[1][i] && _state[1][i] == _state[2][i] && _state[0][i] != 0){ + _winner = _state[0][i]==1?PLAYER_X:PLAYER_Y + console.log(_winner); + _gameOver = true + } + } + //check diagonals + if(_state[0][0] == _state[1][1] && _state[1][1] == _state[2][2] && _state[0][0] != 0){ + _winner = _state[0][0]==1?PLAYER_X:PLAYER_Y + console.log(_winner); + _gameOver = true + } + if(_state[0][2] == _state[1][1] && _state[1][1] == _state[2][0] && _state[0][2] != 0){ + _winner = _state[0][2]==1?PLAYER_X:PLAYER_Y + console.log(_winner); + _gameOver = true + } + //check draw + let isTie = true + for(let i=0;i{ + cell.gameOver() + }) + } + if(_gameOver){ + if(isTie) + document.querySelector(".result").textContent = "Game Tied" + else if(_winner == PLAYER_X) + document.querySelector(".result").textContent = "Player X Won" + else if(_winner == PLAYER_Y) + document.querySelector(".result").textContent = "Player O Won" + } + } + const reset = ()=>{ + _gameOver = false + _currPlayer = PLAYER_X + for(let i = 0; i < _state.length; i++){ + _state[i] = new Array(3).fill(0) + } + } + return{select, getChar, isGameOver, reset} +})() +let cells = [] +const cellFactory = (element)=> { + const _number = cells.length + let _value = 0 + const _element = element + let _playable = true; + this.getCellNum = ()=>_number + this.isPlayable = ()=> _playable + this.getElement = ()=> _element + element.addEventListener('click',()=>{ + // console.log(_number); + if(_playable && !gameBoard.isGameOver()){ + _element.textContent = gameBoard.getChar() + _playable = false + _element.classList.remove('playable'); + + gameBoard.select(_number) + } + }) + this.select = ()=>{ + _element.textContent = gameBoard.getChar() + _playable = false + _element.classList.remove('playable'); + } + this.reset = ()=>{ + _element.textContent = '' + _playable = true + _element.classList.add('playable'); + } + this.gameOver = ()=>{ + _playable = false + _element.classList.remove('playable'); + } + this.setPlayable = (value)=>{ + _playable = value + _element.classList.remove('playable'); + } + return {getCellNum,isPlayable, getElement, reset, gameOver,select,setPlayable} +} +document.querySelectorAll(".cell").forEach(cellElmt=>{ + cell = cellFactory(cellElmt) + cells[cell.getCellNum()] = cell +}) + +let resetButton = document.querySelector(".reset") +resetButton.onclick = ()=>{ + document.querySelector(".result").textContent = " " + gameBoard.reset() + cells.forEach(cell=>cell.reset()) + if(!X_human) + player_controller.notify(PLAYER_X,[[0,0,0],[0,0,0],[0,0,0]]) + +}; + +if(!X_human){ + console.log("object"); + player_controller.notify(PLAYER_X,[[0,0,0],[0,0,0],[0,0,0]]) +} +if(!X_human && !O_human){ + //make all the cells unplayable + cells.forEach(cell=>{ + cell.setPlayable(false) + }) +} + + + +// set up selector for bot and human +selector_x = document.querySelector("#player_x") +selector_o = document.querySelector("#player_o") +// when a new drop down is selected, update the player_controller +selector_x.onchange = ()=>{ + document.querySelector(".result").textContent = " " + X_human = selector_x.value == "human" + gameBoard.reset() + cells.forEach(cell=>cell.reset()) + if(!X_human) + player_controller.notify(PLAYER_X,[[0,0,0],[0,0,0],[0,0,0]]) + + +} +selector_o.onchange = ()=>{ + document.querySelector(".result").textContent = " " + O_human = selector_o.value == "human" + gameBoard.reset() + cells.forEach(cell=>cell.reset()) + if(!X_human) + player_controller.notify(PLAYER_X,[[0,0,0],[0,0,0],[0,0,0]]) +} \ No newline at end of file diff --git a/pointless-tic-tac-toe/style.css b/pointless-tic-tac-toe/style.css new file mode 100644 index 00000000..4185909c --- /dev/null +++ b/pointless-tic-tac-toe/style.css @@ -0,0 +1,104 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +/* CSS RESET END */ + +html{ + height: 100%; +} +body{ + min-height: 100%; + font-family: 'Orbitron', sans-serif; +} + +.board{ + max-width: 600px; +} +.row{ + display: flex; + width: 100%; + min-height:20px ; + margin-bottom: 5px; +} +.cell{ + width: 75px; + height: 75px; + border: none; + margin-right: 5px; + display: flex; + justify-content: center; + align-items: center; + background-color: #f5f5f5; + border-radius: 10px; + transition: all 0.2s ease-in-out; +} +.playable:hover{ + background-color: #e9e9e9; + scale: 1.1; + box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; +} + +.reset{ + background-color: rgb(59, 59, 59); + color: #fff; + padding: 10px; + border-radius: 10px; + font-size: 20px; + font-family: 'Orbitron', sans-serif; + cursor: pointer; +} + +select{ + /* border-radius: 10px; */ + padding: 15px; + border-radius: 10px; + font-size: large; + font-family: 'Orbitron', sans-serif; +} +body{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap : 20px; +} \ No newline at end of file From 65bea1fd79ac440f4332954744b1317180aa318a Mon Sep 17 00:00:00 2001 From: nishith-hbf <115030717+nishith-hbf@users.noreply.github.com> Date: Sun, 30 Oct 2022 23:09:12 +0530 Subject: [PATCH 2/9] Add files via upload --- README.md | 62 ++---------------------------------------------------- index.html | 34 ++++++++++++++++++++++++++++++ script.js | 46 ++++++++++++++++++++++++++++++++++++++++ style.css | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 60 deletions(-) create mode 100644 index.html create mode 100644 script.js create mode 100644 style.css diff --git a/README.md b/README.md index 90c3056e..d9daaf9d 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,2 @@ -

- General Projects -

- -GitHub contributors -License Badge - -[![GitHub PRs](https://img.shields.io/github/issues-pr/codemistic/General-Projects?style=social&logo=github)](https://github.com/codemistic/General-Projects/pulls) [![GitHub forks](https://img.shields.io/github/forks/codemistic/General-Projects?logo=git)](https://github.com/codemistic/General-Projects/network) - - -Steps to contribute in this repository - - 1. Fork this repo - 2. Create a new folder/directory for your projects - 3. Add useful code for the open-source community - 4. Make pull request - 5. Now, it time for review (Don't worry, our team we will review your Pull Request(PR) within 6 hours. - -## Maintainers (Our Team for HacktoberFest) - - - - - - - - -
- - Gantavya -
- Gantavya Malviya -
-
- - -
- Kirtan -
-
- - Adarsh -
- Adarsh jaiswal -
-
- -## Top Contributors -Update in progress.... - -### Thanks for visiting! -### Regards, -### Team CodeMistic -[![Linkedin](https://img.shields.io/badge/-LinkedIn-blue?style=flat-square&logo=Linkedin&logoColor=white&link=https://www.linkedin.com/company/codemistic/)](https://www.linkedin.com/company/codemistic/) -[![Twitter](https://img.shields.io/badge/-Twitter-%231DA1F2.svg?style=flat-square&logo=twitter&logoColor=white&link=https://www.twitter.com/codemistic/)](https://www.twitter.com/codemistic/) -[![Instagram](https://img.shields.io/badge/-Instagram-red?style=flat-square&logo=Instagram&logoColor=white&link=https://www.instagram.com/codemistic.in/)](https://www.instagram.com/codemistic.in/) -[![GitHub](https://img.shields.io/badge/-Github-%23100000.svg?&style=flat-square&logo=github&logoColor=white&link=https://www.github.com/codemistic/)](https://www.github.com/codemistic/) -[![views](https://komarev.com/ghpvc/?username=codemistic&label=Profile%20views&color=0e75b6&style=flat)](https://github.com/codemistic) - -Custom badge for codemistic Group +### +Simple webpage that allows the user whatever they feel like. \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..f8d5be34 --- /dev/null +++ b/index.html @@ -0,0 +1,34 @@ + + + + + + + DrawAI + + + + + + + + +

DrawAI

+
+ +
+ +
+
+ 16 +
+ +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 00000000..12c4ed5a --- /dev/null +++ b/script.js @@ -0,0 +1,46 @@ +let side = 16; +let grid = document.querySelector(".grid"); +let sideSize = document.querySelector(".sideSize"); +let drawing = true; +let color = "#658CE6"; +function createGrid(){ + for(let i=0; i{ + drawing = drawing==false? true: false; + console.log(drawing); + }); + pixel.addEventListener('mouseover',()=>{ + if(drawing){ + pixel.style.backgroundColor = color; + } + }) + row.appendChild(pixel) + } + grid.appendChild(row); + } + // document.body.appendChild(grid); +} +function resetGrid(){ + grid.textContent="" + createGrid(); +} +createGrid(); + +let slider = document.querySelector("#sizeSlider"); +slider.addEventListener('change',()=>{ + side = slider.value; + if(side>100 || side<0) side = 100; + sideSize.innerText = side; + resetGrid(); +}); +slider.addEventListener('input',()=>{ + sideSize.innerText = slider.value; +}); + +let colorPicker = document.querySelector("#colorPicker"); +colorPicker.addEventListener('input',()=>{color=colorPicker.value;}); \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 00000000..c22ffc22 --- /dev/null +++ b/style.css @@ -0,0 +1,53 @@ +body{ + /* display: flex; */ + /* justify-content: center; */ + /* align-items: center; */ + + background-color: #F8F0E3; + font-family: 'Luckiest Guy', cursive; +} +h1{ + display: flex; + justify-content: center; + font-size: xx-large; +} +.content{ + display: flex; + flex-direction: column-reverse; + align-items: center; +} +.options{ + display: flex; + padding-top: 30px; + align-items: center; + gap: 12px; +} +.sizeSelector{ + display: flex; + flex-direction: column; + align-items: center; +} +.gridContainer{ + display: flex; + justify-content: center; +} +.grid{ + justify-self: end; + display: flex; + flex-direction: column; + justify-content: stretch; + height: 500px; + width: 500px; + box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; + background-color: white; +} +.row{ + flex-grow: 1; + display: flex; + justify-content: stretch; +} + +.pixel{ + /* border: 1px solid black; */ + flex-grow: 1; +} \ No newline at end of file From 426bd257c88da54b47da133a0dc8c26c515b04fa Mon Sep 17 00:00:00 2001 From: nishith-hbf <115030717+nishith-hbf@users.noreply.github.com> Date: Sun, 30 Oct 2022 23:09:52 +0530 Subject: [PATCH 3/9] Delete style.css --- style.css | 53 ----------------------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 style.css diff --git a/style.css b/style.css deleted file mode 100644 index c22ffc22..00000000 --- a/style.css +++ /dev/null @@ -1,53 +0,0 @@ -body{ - /* display: flex; */ - /* justify-content: center; */ - /* align-items: center; */ - - background-color: #F8F0E3; - font-family: 'Luckiest Guy', cursive; -} -h1{ - display: flex; - justify-content: center; - font-size: xx-large; -} -.content{ - display: flex; - flex-direction: column-reverse; - align-items: center; -} -.options{ - display: flex; - padding-top: 30px; - align-items: center; - gap: 12px; -} -.sizeSelector{ - display: flex; - flex-direction: column; - align-items: center; -} -.gridContainer{ - display: flex; - justify-content: center; -} -.grid{ - justify-self: end; - display: flex; - flex-direction: column; - justify-content: stretch; - height: 500px; - width: 500px; - box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; - background-color: white; -} -.row{ - flex-grow: 1; - display: flex; - justify-content: stretch; -} - -.pixel{ - /* border: 1px solid black; */ - flex-grow: 1; -} \ No newline at end of file From 3bcc9e92c2e783e69c584571a51a6d3c52617a0d Mon Sep 17 00:00:00 2001 From: nishith-hbf <115030717+nishith-hbf@users.noreply.github.com> Date: Sun, 30 Oct 2022 23:10:07 +0530 Subject: [PATCH 4/9] Delete script.js --- script.js | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) delete mode 100644 script.js diff --git a/script.js b/script.js deleted file mode 100644 index 12c4ed5a..00000000 --- a/script.js +++ /dev/null @@ -1,46 +0,0 @@ -let side = 16; -let grid = document.querySelector(".grid"); -let sideSize = document.querySelector(".sideSize"); -let drawing = true; -let color = "#658CE6"; -function createGrid(){ - for(let i=0; i{ - drawing = drawing==false? true: false; - console.log(drawing); - }); - pixel.addEventListener('mouseover',()=>{ - if(drawing){ - pixel.style.backgroundColor = color; - } - }) - row.appendChild(pixel) - } - grid.appendChild(row); - } - // document.body.appendChild(grid); -} -function resetGrid(){ - grid.textContent="" - createGrid(); -} -createGrid(); - -let slider = document.querySelector("#sizeSlider"); -slider.addEventListener('change',()=>{ - side = slider.value; - if(side>100 || side<0) side = 100; - sideSize.innerText = side; - resetGrid(); -}); -slider.addEventListener('input',()=>{ - sideSize.innerText = slider.value; -}); - -let colorPicker = document.querySelector("#colorPicker"); -colorPicker.addEventListener('input',()=>{color=colorPicker.value;}); \ No newline at end of file From d40fca7f236a0d36457e2f095db7a3c8fad059a0 Mon Sep 17 00:00:00 2001 From: nishith-hbf <115030717+nishith-hbf@users.noreply.github.com> Date: Sun, 30 Oct 2022 23:10:28 +0530 Subject: [PATCH 5/9] Delete index.html --- index.html | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 index.html diff --git a/index.html b/index.html deleted file mode 100644 index f8d5be34..00000000 --- a/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - DrawAI - - - - - - - - -

DrawAI

-
- -
- -
-
- 16 -
- -
-
-
-
-
- - - - \ No newline at end of file From 92b2cb9e9506f876a9adab989681c8bd1eaf79a5 Mon Sep 17 00:00:00 2001 From: nishith-hbf Date: Sun, 30 Oct 2022 22:58:16 +0530 Subject: [PATCH 6/9] initial commit --- drawAI/README.md | 1 + drawAI/index.html | 33 +++++++++++++++++++++++++++++ drawAI/script.js | 46 ++++++++++++++++++++++++++++++++++++++++ drawAI/style.css | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 drawAI/README.md create mode 100644 drawAI/index.html create mode 100644 drawAI/script.js create mode 100644 drawAI/style.css diff --git a/drawAI/README.md b/drawAI/README.md new file mode 100644 index 00000000..cac646e7 --- /dev/null +++ b/drawAI/README.md @@ -0,0 +1 @@ +Simple webpage that allows the user whatever they feel like. \ No newline at end of file diff --git a/drawAI/index.html b/drawAI/index.html new file mode 100644 index 00000000..457868f1 --- /dev/null +++ b/drawAI/index.html @@ -0,0 +1,33 @@ + + + + + + + DrawAI + + + + + + + + +

DrawAI

+
+ +
+ +
+
+ 16 +
+ +
+
+
+
+
+ + + \ No newline at end of file diff --git a/drawAI/script.js b/drawAI/script.js new file mode 100644 index 00000000..12c4ed5a --- /dev/null +++ b/drawAI/script.js @@ -0,0 +1,46 @@ +let side = 16; +let grid = document.querySelector(".grid"); +let sideSize = document.querySelector(".sideSize"); +let drawing = true; +let color = "#658CE6"; +function createGrid(){ + for(let i=0; i{ + drawing = drawing==false? true: false; + console.log(drawing); + }); + pixel.addEventListener('mouseover',()=>{ + if(drawing){ + pixel.style.backgroundColor = color; + } + }) + row.appendChild(pixel) + } + grid.appendChild(row); + } + // document.body.appendChild(grid); +} +function resetGrid(){ + grid.textContent="" + createGrid(); +} +createGrid(); + +let slider = document.querySelector("#sizeSlider"); +slider.addEventListener('change',()=>{ + side = slider.value; + if(side>100 || side<0) side = 100; + sideSize.innerText = side; + resetGrid(); +}); +slider.addEventListener('input',()=>{ + sideSize.innerText = slider.value; +}); + +let colorPicker = document.querySelector("#colorPicker"); +colorPicker.addEventListener('input',()=>{color=colorPicker.value;}); \ No newline at end of file diff --git a/drawAI/style.css b/drawAI/style.css new file mode 100644 index 00000000..c22ffc22 --- /dev/null +++ b/drawAI/style.css @@ -0,0 +1,53 @@ +body{ + /* display: flex; */ + /* justify-content: center; */ + /* align-items: center; */ + + background-color: #F8F0E3; + font-family: 'Luckiest Guy', cursive; +} +h1{ + display: flex; + justify-content: center; + font-size: xx-large; +} +.content{ + display: flex; + flex-direction: column-reverse; + align-items: center; +} +.options{ + display: flex; + padding-top: 30px; + align-items: center; + gap: 12px; +} +.sizeSelector{ + display: flex; + flex-direction: column; + align-items: center; +} +.gridContainer{ + display: flex; + justify-content: center; +} +.grid{ + justify-self: end; + display: flex; + flex-direction: column; + justify-content: stretch; + height: 500px; + width: 500px; + box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; + background-color: white; +} +.row{ + flex-grow: 1; + display: flex; + justify-content: stretch; +} + +.pixel{ + /* border: 1px solid black; */ + flex-grow: 1; +} \ No newline at end of file From 1153632801ebec159334735e49ac733ad5426196 Mon Sep 17 00:00:00 2001 From: nishith-hbf Date: Sun, 30 Oct 2022 23:14:58 +0530 Subject: [PATCH 7/9] initial commit --- drawAI/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/drawAI/README.md b/drawAI/README.md index cac646e7..d9daaf9d 100644 --- a/drawAI/README.md +++ b/drawAI/README.md @@ -1 +1,2 @@ +### Simple webpage that allows the user whatever they feel like. \ No newline at end of file From 5aecefcc4908dc39829053b3bb5c21bd0b4c1ca2 Mon Sep 17 00:00:00 2001 From: nishith-hbf Date: Sun, 30 Oct 2022 23:15:13 +0530 Subject: [PATCH 8/9] final changes --- drawAI/index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drawAI/index.html b/drawAI/index.html index 457868f1..f8d5be34 100644 --- a/drawAI/index.html +++ b/drawAI/index.html @@ -30,4 +30,5 @@

DrawAI

- \ No newline at end of file + + \ No newline at end of file From ce981ce81d48b0bfb8e0b68f3d5896440af696d9 Mon Sep 17 00:00:00 2001 From: nishith-hbf Date: Sun, 30 Oct 2022 23:17:42 +0530 Subject: [PATCH 9/9] speech recognition assistant with vosk-api --- speech_recognition_vosk.py | 216 +++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 speech_recognition_vosk.py diff --git a/speech_recognition_vosk.py b/speech_recognition_vosk.py new file mode 100644 index 00000000..385f48b4 --- /dev/null +++ b/speech_recognition_vosk.py @@ -0,0 +1,216 @@ +from settings import Config +from s2t_class import Speech2Text, test +import openpyxl +import json +import sys +import traceback +import os + + +class ModExcel: + def __init__(self, path="samples/samples.xlsx", + config=Config().get_config()): + self.path: str = path + self.workbook = openpyxl.load_workbook(path) + self.row: int = 1 + self.col: int = 1 + self.config: dict = config + self.sheet = self.workbook.active + + def getSheet(self): + return self.sheet + + def getCell(self): + try: + return self.sheet.cell(row=self.row, column=self.col) + except Exception: + return None + + def locate(self, *args) -> list: + flag: int = 0 + for i in range(1, self.sheet.max_row + 1): + for j in range(1, self.sheet.max_column + 1): + for k in args[0]: + cv = self.sheet.cell(row=i, column=j) + if k in cv.value: + print( + f"\n\n{k} found in {cv.address} having {cv.value}", + end="\n\n" + ) + flag += 1 + + if flag == 0: + print("\n\nSorry, no result found.\n\n") + + def getDetails(self, *args): + # print("\n\ngetDetails() invoked!\n\n") + # print(f"Arguments = {args}") + cell = self.getCell() + + if cell is not None: + if ["address"] in args: + print( + f"\n\nCurrent cell address is {cell.coordinate}\n\n" + ) + # return self.getCell().coordinate + elif ["value"] in args: + print(f"\n\nCurrent cell value is {cell.value}\n\n") + # return self.getCell().value + elif ["sheet"] in args: + print(f"\n\n\n\nCurrent sheet is {self.getSheet()}\n\n\n\n") + elif ["workbook"] in args: + print(f"\n\n\n\nCurrent workbook is {self.getSheet()}\n\n\n\n") + else: + print(f"\n\nRow {self.row}, Column {self.col} is an invalid address.") + print(f"For this worksheet, rows lie in the range [1,{self.sheet.max_row}], and columns lie in the range [1,{self.sheet.max_column}]\n\n") + + def navigate(self, *args): + for i in args[0]: + if i.lower() == "right": + print("\n\nMoving one column right\n\n") + self.col += 1 + elif i.lower() == "left": + print("\n\nMoving one column left\n\n") + self.col -= 1 + elif i.lower() == "up": + print("\n\nMoving one row up\n\n") + self.row -= 1 + elif i.lower() == "down": + print("\n\nMoving one row down\n\n") + self.row += 1 + else: + print("Sorry, command not recognized :(") + + def setValue(self, cmd: list): + val = cmd[0] + cell = self.getCell() + try: + cell.value = val + print("\n\nModified the concerned excel file.\n\n") + self.workbook.save(self.path) + return True + except Exception: + print("\n\nCouldn't modify the concerned excel file.\n\n") + return False + + +def parsecmd(cmd: str) -> list: + # Enter ABCD and move right and down and get address and value + + tree: list = [[y.strip() for y in x.strip().split()] for x in cmd.split("and ")] + tree2: list = [] + + for i in range(len(tree)): + if len(tree[i]) == 1: + tree2[-1] += list(tree[i]) + else: + tree2.append(tree[i]) + + # print(tree2) + + for i in tree2: + for j in range(len(i)): + if j == 0: + i[j] = i[j].lower() + + print(f"\n\nCrudely Parsed Tree: {tree2}") + + tree3: list = [] + + keyword: str = "" + arg = None + tpl = None + + for i in tree2: + if i[0] == "enter": + keyword = i[0] + arg = " and ".join(i[1:]) + tpl = tuple((keyword, arg)) + + else: + keyword = i[0] + arg = i[1:] + tpl = [] + for i in range(len(arg)): + tpl += [tuple((keyword, arg[i]))] + + if type(tpl) == type(tuple()): + tree3.append(tpl) + elif type(tpl) == type([]): + tree3 += tpl + else: + continue + + print(f"\n\nRefined Parsed Tree: {json.dumps(tree3, indent=4)}") + del tree + del tree2 + + return tree3 + + +def execute(xl, cfg, parsed_tree): + commands: list = list([x[0] for x in parsed_tree]) + attributes: list = list([x[1] for x in parsed_tree]) + + print(f"\n\nParsed syntax: {parsed_tree}\n\n") + print(f"\n\nParsed commands: {commands}\n\n") + + print("\n\nConfiguration available:\n\n") + for i in cfg.keys(): + print(f"{i}\t{cfg[i]}") + + for i in range(len(commands)): + if commands[i] in cfg.keys(): + print(f"\n\nCommand recognized: {commands[i]}.") + print(f"Parameters: {attributes[i]}\n\n") + cmd = f"xl.{cfg[commands[i]]}(['{attributes[i]}'])" + + print(f"\n\nBuilt command: {cmd}\n\n") + exec(cmd) + else: + print( + f"\n\nCommand {commands[i]} isn't valid... \n\n" + ) + + +def driver_excelmod(): + s2t = Speech2Text(mode="mic", src="vosk", output="a_test.txt") + cfg: dict = Config().get_config() + xl = ModExcel(config=cfg) + + while True: + try: + if s2t.src == "vosk": + text: str = json.loads(s2t.listen())["text"] + elif s2t.src == "google": + text: str = s2t.listen() + print(f"\n\nCommand given: {text}\n\n") + + execute(xl, cfg, parsecmd(text)) + except Exception as e: + traceback.print_exc() + print("\n\nAn error occured. Error details: \t", e) + + +def test_excelmod(): + test_inst_vosk = Speech2Text( + mode="rec", + loc="/media/Samsung SSD 970 EVO 1TB/Projects/NLP Project/tests/input/Instructions-for-the-voice-recog-system.wav", + src="vosk", + output="/mediaSamsung SSD 970 EVO 1TB/Projects/NLP Project/tests/output/random_test.txt" + ) + + text: str = json.loads(test_inst_vosk.listen())["text"] + + cfg: dict = Config().get_config() + xl = ModExcel(config=cfg) + + execute(xl, cfg, parsecmd(text)) + os.remove("/mediaSamsung SSD 970 EVO 1TB/Projects/NLP Project/tests/output/random_test.txt") + + +if __name__ == "__main__": + if len(sys.argv) > 1: + test_excelmod() + else: + driver_excelmod()