Commit 07a5259d authored by Hirusha's avatar Hirusha

learning

learning
parent f7189a9c
File added
{ {
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.formatOnPaste": false "editor.formatOnPaste": false,
"[typescriptreact]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
}
} }
\ No newline at end of file
This diff is collapsed.
File added
import React from 'react' import React from 'react'
import logo from './logo.svg' import { BrowserRouter, Routes, Route } from 'react-router-dom'
import './App.css' import './App.css'
import HomePage from './Pages/Learn/HomePage/Home.page'
import DrawerAppBar from './Components/DrawerAppBar/DrawerAppBar'
import RegisterPage from './Pages/Learn/RegisterPage/Register.page'
import Login from './Pages/Learn/LoginPage/Login.page'
import SelectDifficultyPage from './Pages/Learn/SelectDifficultyPage/SelectDifficulty.page'
import ResourcesPage from './Pages/Learn/ResourcesPage/Resources.page'
import MoreResourcesPage from './Pages/Learn/MoreResourcesPage/MoreResources.page'
import MoreResourcesDetailsPage from './Pages/Learn/MoreResourcesDetailsPage/MoreResourcesDetails.page'
import GameDetails from './Pages/Learn/GameDetailsPage/GameDetails.page'
import GamePage from './Pages/Learn/GamePage/game.page'
// import ResourcesPages from './Pages/Learn/backup/Resources.page';
function App() { function App() {
return ( return (
<div className='App'> <BrowserRouter>
<header className='App-header'> <Routes>
<img src={logo} className='App-logo' alt='logo' /> <Route element={<DrawerAppBar />}>
<p> <Route path='/' element={<HomePage />} />
Edit <code>src/App.tsx</code> and save to reload. <Route path='/select' element={<SelectDifficultyPage />} />
</p> <Route path='/resources/:level' element={<ResourcesPage />} />
<a <Route path='/moreResources/:resourcesId' element={<MoreResourcesPage />} />
className='App-link' <Route path='/moreResourcesDetails/:itemId' element={<MoreResourcesDetailsPage />} />
href='https://reactjs.org' <Route path='/game/:resourcesId' element={<GamePage />} />
target='_blank' <Route path='/gameDetails/:gameId' element={<GameDetails />} />
rel='noopener noreferrer' <Route path='/register' element={<RegisterPage />} />
> <Route path='/login' element={<Login />} />
Learn React {/* <Route path="/c" element={<ResourcesPages />} /> */}
</a> </Route>
</header> </Routes>
</div> </BrowserRouter>
) )
} }
......
import * as React from 'react'
import AppBar from '@mui/material/AppBar'
import Box from '@mui/material/Box'
import CssBaseline from '@mui/material/CssBaseline'
import Divider from '@mui/material/Divider'
import Drawer from '@mui/material/Drawer'
import IconButton from '@mui/material/IconButton'
import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem'
import ListItemButton from '@mui/material/ListItemButton'
import ListItemText from '@mui/material/ListItemText'
import MenuIcon from '@mui/icons-material/Menu'
import Toolbar from '@mui/material/Toolbar'
import Typography from '@mui/material/Typography'
import { Outlet, useNavigate, Link } from 'react-router-dom'
import Button from '@mui/material/Button'
import Avatar from '@mui/material/Avatar'
import logo from '../../Assests/Images/logo.png'
import { getUserId, deleteUserId } from '../../Config'
interface Props {
window?: () => Window
}
const drawerWidth = 240
const navItems = ['Home', 'About', 'Contact']
export default function DrawerAppBar(props: Props) {
const navigate = useNavigate()
const { window } = props
const [mobileOpen, setMobileOpen] = React.useState(false)
const handleDrawerToggle = () => {
setMobileOpen((prevState) => !prevState)
}
const handleLogOut = () => {
deleteUserId()
navigate('/')
}
const handleLogIn = () => {
navigate('/login')
}
const handleRegister = () => {
navigate('/register')
}
const drawer = (
<Box onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}>
<Typography variant='h6' sx={{ my: 2 }}>
MUI
</Typography>
<Avatar alt='Remy Sharp' src='/Assests/Images/logo.png' />
<Divider />
<List>
{navItems.map((item) => (
<ListItem key={item} disablePadding>
<ListItemButton sx={{ textAlign: 'center' }}>
<ListItemText primary={item} />
</ListItemButton>
</ListItem>
))}
</List>
</Box>
)
const container = window !== undefined ? () => window().document.body : undefined
return (
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar component='nav' sx={{ backgroundColor: '#ffffff' }}>
<Toolbar>
<IconButton
color='inherit'
aria-label='open drawer'
edge='start'
onClick={handleDrawerToggle}
sx={{ mr: 2, display: { sm: 'none' } }}
>
<MenuIcon />
</IconButton>
{/* <Typography
variant="h6"
component="div"
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
>
MUI
</Typography> */}
<img
src={logo}
alt='Description of your image'
style={{ width: '150px', height: '35px', marginLeft: '30px' }}
/>
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'row', justifyContent: 'end' }}>
{getUserId() ? (
<Box sx={{ display: { xs: 'none', sm: 'block' }, mr: 10 }}>
<Button
component={Link}
to={'/select'}
sx={{ color: '#000000', fontWeight: '700' }}
>
Learn
</Button>
<Button component={Link} to={'/'} sx={{ color: '#000000', fontWeight: '700' }}>
Dashboad
</Button>
<Button
onClick={handleLogOut}
sx={{
color: '#ffffff',
fontWeight: '500',
backgroundColor: '#7950F1',
ml: 5,
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
},
}}
>
Sign Out
</Button>
</Box>
) : (
<Box sx={{ display: { xs: 'none', sm: 'block' }, mr: 10 }}>
<Button
onClick={handleLogIn}
sx={{
color: '#7950F1',
fontWeight: '700',
fontSize: 16,
mr: 2,
':hover': {
color: '#5a2ce6',
},
}}
>
Sign In
</Button>
<Button
onClick={handleRegister}
sx={{
color: '#ffffff',
fontWeight: '700',
backgroundColor: '#7950F1',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
},
}}
>
Sign Up
</Button>
</Box>
)}
</Box>
</Toolbar>
</AppBar>
<nav>
<Drawer
container={container}
variant='temporary'
open={mobileOpen}
onClose={handleDrawerToggle}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
sx={{
display: { xs: 'block', sm: 'none' },
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
}}
>
{drawer}
</Drawer>
</nav>
<Box
component='main'
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
mt: 7.5,
width: '100%',
}}
>
<Outlet />
</Box>
</Box>
)
}
import React, { useEffect } from 'react'
import { Box } from '@mui/material'
import Webcam from 'react-webcam'
import axios from 'axios'
interface LiveWebCamProps {
inputData: string
}
const LiveWebCam: React.FC<LiveWebCamProps> = ({ inputData }) => {
const webcamRef = React.useRef<Webcam>(null)
const canvasRef = React.useRef<HTMLCanvasElement>(null)
useEffect(() => {
const intervalId = setInterval(() => {
if (webcamRef.current?.video && canvasRef.current) {
const video = webcamRef.current.video
const frame = webcamRef.current.getScreenshot()
// Get Video Properties
const videoWidth = webcamRef.current.video.videoWidth
const videoHeight = webcamRef.current.video.videoHeight
// Set video width
webcamRef.current.video.width = videoWidth
webcamRef.current.video.height = videoHeight
// Set canvas height and width
const canvas = canvasRef.current
canvas.width = videoWidth
canvas.height = videoHeight
const context = canvas.getContext('2d')
if (frame && context) {
console.log('###### 1 ######')
console.log(inputData)
console.log('###### 1 ######')
axios
.post(
'http://127.0.0.1:5000/predict',
{ frame, inputData },
{
headers: {
'Content-Type': 'application/json',
charset: 'utf-8',
},
},
)
.then((response) => {
console.log('###### 2 ######')
console.log(response.data.predict)
console.log('###### 2 ######')
// Draw the prediction and rectangle on the canvas
canvas.width = video.videoWidth
canvas.height = video.videoHeight
context.drawImage(video, 0, 0, canvas.width, canvas.height)
context.font = '18px Arial'
if (response.data.status) {
context.fillStyle = 'green'
context.strokeStyle = 'green'
} else {
context.fillStyle = 'red'
context.strokeStyle = 'red'
}
context.fillText(`Prediction: ${response.data.prediction}`, 50, 45)
context.lineWidth = 2
context.strokeRect(70, 70, 180, 180)
})
.catch((error) => {
console.error('Error:', error)
})
}
}
}, 2000) // Adjust the interval as needed
return () => clearInterval(intervalId)
}, [])
return (
<Box
sx={{
position: 'relative',
marginLeft: '-300px',
width: '600px',
height: '450px',
}}
>
<Webcam
ref={webcamRef}
muted={true}
style={{
position: 'absolute',
width: '100%',
height: '100%',
}}
/>
<canvas
ref={canvasRef}
style={{
position: 'absolute',
width: '100%',
height: '100%',
}}
/>
</Box>
)
}
export default LiveWebCam
export const baseURL = 'http://127.0.0.1:8500'
export const reactBaseURL = 'http://localhost:3000'
export const setUserId = (userId: string) => {
console.log('############ setUserId ##############')
console.log(userId)
console.log('############ setUserId ##############')
localStorage.setItem('userId', userId)
}
export const getUserId = (): string | null => {
console.log('############ getUserId ##############')
console.log(localStorage.getItem('userId'))
console.log('############ getUserId ##############')
return localStorage.getItem('userId')
}
export const deleteUserId = () => {
console.log('############ deleteUserId ##############')
localStorage.removeItem('userId')
}
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getByGameId = async (gameId: string) => {
try {
const { data } = await axios.get(baseURL + '/games/' + gameId)
return data
} catch (error) {
console.error(error)
}
}
import React, { useEffect, useState } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { Box, Button, Card, CardContent, CardMedia, Typography, Container } from '@mui/material'
import { getByGameId } from './GameDetails.api'
import Swal from 'sweetalert2'
const GameDetails: React.FC = () => {
const navigate = useNavigate()
const { gameId } = useParams()
const [video, setVideo] = useState<any>('')
const [q, setQ] = useState<any>('')
const [a1, setA1] = useState<any>('')
const [a2, setA2] = useState<any>('')
const [a3, setA3] = useState<any>('')
const [a4, setA4] = useState<any>('')
const [correct, setCorrect] = useState<any>('')
const [level, setLevel] = useState<any>('')
useEffect(() => {
if (gameId) {
getByGameId(gameId)
.then((result) => {
setVideo(result.data.video)
setQ(result.data.question)
setA1(result.data.a1)
setA2(result.data.a2)
setA3(result.data.a3)
setA4(result.data.a4)
setCorrect(result.data.correct)
setLevel(result.data.level)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [gameId])
const handleAnswerClick = (answer: any) => {
if (correct === answer) {
void Swal.fire({
position: 'center',
icon: 'success',
title: 'Correct Answer',
showConfirmButton: false,
timer: 2000,
}).then(() => {
navigate('/game/' + level)
})
} else {
void Swal.fire({
position: 'center',
icon: 'error',
title: 'Wornge Answer',
showConfirmButton: false,
timer: 2000,
}).then(() => {
navigate('/game/' + level)
})
}
}
return (
<Container maxWidth='sm' sx={{ mt: 4 }}>
<Box sx={{ maxWidth: 400, mx: 'auto' }}>
<Card>
<CardMedia
component='video'
src={video}
controls
autoPlay
muted
title='Game Video'
sx={{ height: 240 }}
/>
<CardContent>
<Typography gutterBottom variant='h5' component='div' textAlign='center'>
{q}
</Typography>
<Button
variant='contained'
color='primary'
onClick={() => handleAnswerClick(a1)}
sx={{ display: 'block', width: '100%', mb: 2 }}
>
{a1}
</Button>
<Button
variant='contained'
color='primary'
onClick={() => handleAnswerClick(a2)}
sx={{ display: 'block', width: '100%', mb: 2 }}
>
{a2}
</Button>
<Button
variant='contained'
color='primary'
onClick={() => handleAnswerClick(a3)}
sx={{ display: 'block', width: '100%', mb: 2 }}
>
{a3}
</Button>
<Button
variant='contained'
color='primary'
onClick={() => handleAnswerClick(a4)}
sx={{ display: 'block', width: '100%', mb: 2 }}
>
{a4}
</Button>
</CardContent>
</Card>
</Box>
</Container>
)
}
export default GameDetails
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getUnlockGameByResourcesId = async (resourcesId: string) => {
try {
const { data } = await axios.get(baseURL + '/games//' + resourcesId)
return data
} catch (error) {
console.error(error)
}
}
export const getLockGameByResourcesId = async (resourcesId: string) => {
try {
const { data } = await axios.get(baseURL + '/games///' + resourcesId)
return data
} catch (error) {
console.error(error)
}
}
import { Box, Typography } from '@mui/material'
import LockIcon from '@mui/icons-material/Lock'
import LockOpenIcon from '@mui/icons-material/LockOpen'
import React, { useState, useEffect } from 'react'
import { useParams, Link } from 'react-router-dom'
// import { Box, Typography } from '@mui/material';
import { getUnlockGameByResourcesId, getLockGameByResourcesId } from './game.api'
export default function GamePage() {
const { resourcesId } = useParams()
const [gamesUnlock, setGamesUnlock] = useState<any>([])
const [gamesLock, setGamesLock] = useState<any>([])
useEffect(() => {
if (resourcesId) {
getUnlockGameByResourcesId(resourcesId)
.then((result) => {
setGamesUnlock(result.data)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [resourcesId])
useEffect(() => {
if (resourcesId) {
getLockGameByResourcesId(resourcesId)
.then((result) => {
setGamesLock(result.data)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [resourcesId])
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mt={4}
mb={4}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{resourcesId} Level Games
</Typography>
</Box>
<Box sx={{ display: 'flex', flexWrap: 'wrap', mr: 30, ml: 30, justifyContent: 'start ' }}>
{gamesUnlock.map((value: any, index: any) => {
return (
<Box
component={Link}
to={'/gameDetails/' + value._id}
sx={{
width: '150px',
height: '150px',
margin: 3.6,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
key={index}
>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={600}
fontSize={20}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Level {value.number}
</Typography>
{value.status === 'L' ? (
<LockIcon style={{ marginTop: '10px', color: '#555555', width: '100%' }} />
) : (
<LockOpenIcon style={{ marginTop: '10px', color: '#555555', width: '100%' }} />
)}
</Box>
)
})}
{gamesLock.map((value: any, index: any) => {
return (
<Box
sx={{
width: '150px',
height: '150px',
margin: 3.6,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
}}
key={index}
>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={600}
fontSize={20}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Level {value.number}
</Typography>
{value.status === 'L' ? (
<LockIcon style={{ marginTop: '10px', color: '#555555', width: '100%' }} />
) : (
<LockOpenIcon style={{ marginTop: '10px', color: '#555555', width: '100%' }} />
)}
</Box>
)
})}
</Box>
</Box>
)
}
import React from 'react'
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
import { useNavigate } from 'react-router-dom'
import mainBanner from '../../../Assests/Images/banner1.jpg'
import homeVideos from '../../../Assests/Images/home-1/video.png'
import homeBrain from '../../../Assests/Images/home-1/brain.png'
import homeClock from '../../../Assests/Images/home-1/clock.png'
import banner2 from '../../../Assests/Images/banner2.jpeg'
import { getUserId } from '../../../Config/index'
import { Parallax } from 'react-parallax'
export default function HomePage() {
const navigate = useNavigate()
const handleStart = () => {
if (getUserId()) {
navigate('/select')
} else {
navigate('/login')
}
}
return (
<Box>
<img
src={mainBanner}
alt='Description of your image'
style={{ width: '100%', height: '100vh' }}
/>
<Box
sx={{
marginTop: '-470px',
display: 'flex',
flexDirection: 'column',
width: '100%',
justifyContent: 'center',
textAlign: 'center',
justifyItems: 'center',
position: 'absolute',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={800}
fontSize={40}
letterSpacing={2}
sx={{
fontFamily: 'samim',
textShadow: '2px 2px 4px rgba(0, 0, 0, 0.3)',
color: '#ffffff',
}}
>
Learn Sinhala Sign Language
</Typography>
</Box>
<Box mt={1.5}>
<Button
onClick={handleStart}
sx={{
backgroundColor: '#7950F1',
color: '#ffffff',
height: 46,
fontWeight: 'bold',
letterSpacing: 2,
borderRadius: 1.5,
width: 220,
mt: 1.5,
':hover': {
backgroundColor: '#5a2ce6',
},
}}
>
Get Start
</Button>
</Box>
</Box>
<Box
sx={{
display: 'flex',
justifyContent: 'center',
flexDirection: 'row',
width: '100%',
mt: 15,
mb: 15,
}}
>
<Box
sx={{ display: 'flex', justifyContent: 'center', flexDirection: 'column', width: '40%' }}
>
<Typography
variant='h6'
component='div'
fontWeight={750}
lineHeight={1}
fontSize={35}
color={'#555555'}
mb={2}
sx={{}}
>
SpeakEzy is a fun and free resource
</Typography>
<Typography
variant='h6'
component='div'
lineHeight={1}
fontWeight={500}
fontSize={25}
color={'#555555'}
width={300}
mb={2}
>
for learning SSL at your own pace.
</Typography>
<Button
sx={{
border: 1,
borderBlockColor: '#7950F1',
backgroundColor: '#ffffff',
color: '#7950F1',
width: 250,
':&hover': {
backgroundColor: 'ActiveBorder',
},
}}
>
Play/Pause Video
</Button>
<Button
sx={{
backgroundColor: '#7950F1',
color: '#ffffff',
width: 250,
mt: 2,
':hover': {
backgroundColor: '#5a2ce6',
},
}}
>
Sign up for free
</Button>
</Box>
<Box
sx={{ display: 'flex', justifyContent: 'center', flexDirection: 'column', width: '45%' }}
>
<img
src={mainBanner}
alt='Description of your image'
style={{ width: '100%', height: '450px' }}
/>
</Box>
</Box>
<Box
sx={{
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
width: '100%',
mb: 20,
}}
>
<Box
sx={{
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: '200px',
paddingRight: '200px',
}}
>
<Box
sx={{ width: '40%', display: 'flex', justifyContent: 'center', justifyItems: 'center' }}
>
<img
src={homeVideos}
alt='Description of your image'
style={{ width: '170px', height: '170px' }}
/>
</Box>
<Box
sx={{
width: '40%',
justifyContent: 'center',
textAlign: 'center',
alignSelf: 'center',
}}
>
<Typography variant='h6' component='div' fontWeight={750} fontSize={35} mb={2} sx={{}}>
SSL in Motion
</Typography>
<Typography variant='h6' component='div' fontWeight={500} fontSize={25} sx={{}}>
See SSL come alive with video-based learning material.
</Typography>
</Box>
</Box>
<Box
sx={{
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: '200px',
paddingRight: '200px',
marginTop: '100px',
}}
>
<Box
sx={{
width: '40%',
justifyContent: 'center',
textAlign: 'center',
alignSelf: 'center',
}}
>
<Typography variant='h6' component='div' fontWeight={750} fontSize={35} mb={2} sx={{}}>
Interactive Learning
</Typography>
<Typography variant='h6' component='div' fontWeight={500} fontSize={25} sx={{}}>
Engage in active learning with interactive exercises, quick lectures, and reviews.
</Typography>
</Box>
<Box
sx={{ width: '40%', display: 'flex', justifyContent: 'center', justifyItems: 'center' }}
>
<img
src={homeBrain}
alt='Description of your image'
style={{ width: '150px', height: '150px' }}
/>
</Box>
</Box>
<Box
sx={{
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: '200px',
paddingRight: '200px',
marginTop: '100px',
}}
>
<Box
sx={{ width: '40%', display: 'flex', justifyContent: 'center', justifyItems: 'center' }}
>
<img
src={homeClock}
alt='Description of your image'
style={{ width: '170px', height: '170px' }}
/>
</Box>
<Box
sx={{
width: '40%',
justifyContent: 'center',
textAlign: 'center',
alignSelf: 'center',
}}
>
<Typography variant='h6' component='div' fontWeight={750} fontSize={35} mb={2} sx={{}}>
Time Efficient
</Typography>
<Typography variant='h6' component='div' fontWeight={500} fontSize={25} sx={{}}>
Focus on learning the ASL most relevant to you with a modular curriculum.
</Typography>
</Box>
</Box>
</Box>
<Parallax bgImage={banner2} strength={500}>
<div style={{ height: 500 }}>
<Typography
variant='h3'
component='div'
fontWeight={800}
fontSize={48}
letterSpacing={2}
sx={{
fontFamily: 'samim',
textShadow: '2px 2px 4px rgba(0, 0, 0, 0.3)',
color: '#ffffff',
textAlign: 'center',
paddingTop: '200px',
}}
>
Let Us Dive to SSL
</Typography>
</div>
</Parallax>
</Box>
)
}
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
interface LoginData {
email: string
password: string
}
export const loginUsers = async (user: LoginData) => {
try {
const { data } = await axios.post(baseURL + '/users/login', user)
return data
} catch (error) {
console.error(error)
}
}
import React, { useState } from 'react'
import { Box, TextField, Button, Typography, Container, Paper } from '@mui/material'
import { useNavigate } from 'react-router-dom'
import Swal from 'sweetalert2'
import { loginUsers } from './Login.api'
import { setUserId } from '../../../Config'
interface LoginData {
email: string
password: string
}
const RegisterPage: React.FC = () => {
const [formData, setFormData] = useState<LoginData>({
email: '',
password: '',
})
const navigate = useNavigate()
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setFormData({ ...formData, [event.target.name]: event.target.value })
}
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
void loginUsers(formData)
.then((result) => {
if (result.message === 'true') {
void Swal.fire({
position: 'center',
icon: 'success',
title: 'Login successful',
showConfirmButton: false,
timer: 2000,
}).then(() => {
const id: string = result.data._id
setUserId(id)
navigate('/select')
})
} else {
void Swal.fire({
position: 'center',
icon: 'error',
title: 'Login failed',
showConfirmButton: false,
timer: 2000,
})
}
})
.catch((error) => {
console.error('Registration failed:', error.response?.data || error.message)
})
}
return (
<Container maxWidth='sm'>
<Paper elevation={3} sx={{ p: 3, mt: 15 }}>
<Typography variant='h4' sx={{ textAlign: 'center', mb: 3 }}>
Login
</Typography>
<Box component='form' noValidate autoComplete='off' onSubmit={handleSubmit}>
<TextField
fullWidth
required
label='Email'
name='email'
type='email'
value={formData.email}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
label='Password'
name='password'
type='password'
value={formData.password}
onChange={handleChange}
sx={{ mb: 3 }}
/>
<Button
type='submit'
variant='contained'
fullWidth
sx={{
py: 1.5,
backgroundColor: '#7950F1',
':hover': {
backgroundColor: '#5a2ce6',
},
}}
>
Login
</Button>
</Box>
</Paper>
</Container>
)
}
export default RegisterPage
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getByResourcesId = async (itemId: string) => {
try {
const { data } = await axios.get(baseURL + '/items/' + itemId)
return data
} catch (error) {
console.error(error)
}
}
import React, { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { Box, Typography } from '@mui/material'
import LiveWebCam from '../../../Components/LiveWebCam/LiveWebCam'
import { getByResourcesId } from './MoreResourcesDetails.api'
export default function MoreResourcesDetailsPage() {
const { itemId } = useParams()
const [image, setImage] = useState<any>('')
const [details, setDetails] = useState<any>('')
const [topic, setTopic] = useState<any>('')
const [label, setLabel] = useState<any>('')
useEffect(() => {
if (itemId) {
getByResourcesId(itemId)
.then((result) => {
setImage(result.data.image)
setDetails(result.data.details)
setTopic(result.data.topic)
setLabel(result.data.label)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [itemId])
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
alignContent: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mt={3}
mb={3}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{topic} : {details}
</Typography>
</Box>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-around',
width: '100%',
height: '100%',
pl: 10,
pr: 10,
}}
>
<Box id='box_id_1' sx={{ width: '600px', height: '450px', justifyContent: 'center' }}>
<Typography
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Get Some Idea
</Typography>
<img
src={image}
alt='Description of your image'
style={{ width: '600px', height: '450px' }}
/>
</Box>
<Box id='box_id_2' sx={{ width: '600px', height: '450px' }}>
<Typography
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Try Your Self
</Typography>
{label ? <LiveWebCam inputData={label} /> : <></>}
</Box>
</Box>
</Box>
)
}
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getByResourcesId = async (resourcesId: string) => {
try {
const { data } = await axios.get(baseURL + '/items//' + resourcesId)
return data
} catch (error) {
console.error(error)
}
}
export const getResourcesById = async (resourcesId: string) => {
try {
const { data } = await axios.get(baseURL + '/resources/' + resourcesId)
return data
} catch (error) {
console.error(error)
}
}
import React, { useEffect, useState } from 'react'
import { useParams, Link } from 'react-router-dom'
import { Box, Typography } from '@mui/material'
import { getByResourcesId, getResourcesById } from './MoreResources.api'
export default function MoreResourcesPage() {
const { resourcesId } = useParams()
const [moreResources, setMoreResources] = useState<any>([])
const [topic, setTopic] = useState<any>('')
const [details, setDetails] = useState<any>('')
useEffect(() => {
if (resourcesId) {
getByResourcesId(resourcesId)
.then((result) => {
setMoreResources(result.data)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [resourcesId])
useEffect(() => {
if (resourcesId) {
getResourcesById(resourcesId)
.then((result) => {
setTopic(result.data.topic)
setDetails(result.data.details)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [resourcesId])
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mt={4}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{topic}
</Typography>
<Typography
variant='h6'
component='div'
fontWeight={400}
fontSize={20}
mb={4}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{details}
</Typography>
</Box>
<Box sx={{ display: 'flex', flexWrap: 'wrap', mr: 30, ml: 30, justifyContent: 'start ' }}>
{moreResources.map((value: any, index: any) => {
return (
<Box
component={Link}
to={'/moreResourcesDetails/' + value._id}
sx={{
width: '200px',
height: '200px',
margin: 3.6,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
key={index}
>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={35}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{value.topic}
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={18}
padding={1}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{value.details}
</Typography>
</Box>
)
})}
</Box>
</Box>
)
}
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
interface RegistrationData {
name: string
email: string
dob: string
gender: string
phone: string
password: string
reEnterPassword: string
}
export const registerUsers = async (user: RegistrationData) => {
try {
const { data } = await axios.post(baseURL + '/users', user)
return data
} catch (error) {
console.error(error)
}
}
import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import {
Box,
TextField,
Button,
FormControl,
InputLabel,
Select,
MenuItem,
Typography,
type SelectChangeEvent,
Container,
Paper,
} from '@mui/material'
import Swal from 'sweetalert2'
import { registerUsers } from './Register.api'
import { setUserId } from '../../../Config'
interface RegistrationData {
name: string
email: string
dob: string
gender: string
phone: string
password: string
reEnterPassword: string
}
const RegisterPage: React.FC = () => {
const navigate = useNavigate()
const [formData, setFormData] = useState<RegistrationData>({
name: '',
email: '',
dob: '',
gender: '',
phone: '',
password: '',
reEnterPassword: '',
})
const handleChange = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | SelectChangeEvent,
) => {
setFormData({ ...formData, [event.target.name]: event.target.value })
}
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
if (formData.password !== formData.reEnterPassword) {
void Swal.fire({
position: 'center',
icon: 'error',
title: 'Passwords do not match.',
showConfirmButton: false,
timer: 2000,
})
} else {
void registerUsers(formData)
.then((result) => {
if (result.message === 'created') {
void Swal.fire({
position: 'center',
icon: 'success',
title: 'Registration successful',
showConfirmButton: false,
timer: 2000,
}).then(() => {
const id: string = result.data._id
setUserId(id)
setTimeout(() => {
navigate('/select')
})
})
} else {
void Swal.fire({
position: 'center',
icon: 'error',
title: 'Registration failed',
showConfirmButton: false,
timer: 2000,
})
}
})
.catch((error) => {
console.error('Registration failed:', error.response?.data || error.message)
})
}
}
return (
<Container maxWidth='sm'>
<Paper elevation={3} sx={{ p: 3, mt: 3 }}>
<Typography variant='h5' sx={{ textAlign: 'center', mb: 2 }}>
Register
</Typography>
<Box component='form' noValidate autoComplete='off' onSubmit={handleSubmit}>
<TextField
fullWidth
required
label='Name'
name='name'
value={formData.name}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
type='email'
label='Email'
name='email'
value={formData.email}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
type='date'
label='Date of Birth'
name='dob'
value={formData.dob}
onChange={handleChange}
InputLabelProps={{ shrink: true }}
sx={{ mb: 2 }}
/>
<FormControl fullWidth sx={{ mb: 2 }}>
<InputLabel id='gender-label'>Gender</InputLabel>
<Select
labelId='gender-label'
name='gender'
value={formData.gender}
label='Gender'
onChange={handleChange}
>
<MenuItem value='male'>Male</MenuItem>
<MenuItem value='female'>Female</MenuItem>
<MenuItem value='other'>Other</MenuItem>
</Select>
</FormControl>
<TextField
fullWidth
required
label='Phone'
name='phone'
value={formData.phone}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
type='password'
label='Password'
name='password'
value={formData.password}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
type='password'
label='Re-enter Password'
name='reEnterPassword'
value={formData.reEnterPassword}
onChange={handleChange}
sx={{ mb: 3 }}
/>
<Button
type='submit'
variant='contained'
fullWidth
sx={{
py: 1.5,
backgroundColor: '#7950F1',
':hover': {
backgroundColor: '#5a2ce6',
},
}}
>
Register
</Button>
</Box>
</Paper>
</Container>
)
}
export default RegisterPage
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getByLevel = async (level: string) => {
try {
const { data } = await axios.get(baseURL + '/resources//' + level)
return data
} catch (error) {
console.error(error)
}
}
export const getAll = async () => {
try {
const { data } = await axios.get(baseURL + '/resources')
return data
} catch (error) {
console.error(error)
}
}
import React, { useEffect, useState } from 'react'
import { useParams, Link } from 'react-router-dom'
import { Box, Typography } from '@mui/material'
import BackHandIcon from '@mui/icons-material/BackHand'
import { getByLevel } from './Resources.api'
export default function ResourcesPage() {
const { level } = useParams()
const [resources, setResources] = useState<any>([])
useEffect(() => {
if (level) {
getByLevel(level)
.then((result) => {
setResources(result.data)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [level])
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={400}
fontSize={20}
mt={6}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{level} :
</Typography>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Recommended Resources
</Typography>
</Box>
<Box sx={{ display: 'flex', flexWrap: 'wrap', mr: 30, ml: 30, justifyContent: 'start' }}>
{resources.map((value: any, index: any) => {
return (
<Box
component={Link}
to={'/moreResources/' + value._id}
sx={{
width: '280px',
margin: 4,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
key={index}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
{level === 'Beginner' ? (
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
) : level === 'Intermediate' ? (
<>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</>
) : (
<>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</>
)}
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{value.topic}
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{value.details}
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={3}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Level {index + 1}
</Typography>
</Box>
)
})}
{level === 'Intermediate' ? (
<Box
component={Link}
to={'/game/' + 'Intermediate'}
sx={{
width: '280px',
margin: 4,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Games
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
pr={2}
pl={2}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Test your know using simple game
</Typography>
</Box>
) : (
<></>
)}
{level === 'Advanced' ? (
<Box
component={Link}
to={'/moreResources/' + 'Advanced'}
sx={{
width: '280px',
margin: 4,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Games
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
pr={2}
pl={2}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Test your know using simple game
</Typography>
</Box>
) : (
<></>
)}
</Box>
</Box>
)
}
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import { Link } from 'react-router-dom'
import BackHandIcon from '@mui/icons-material/BackHand'
export default function SelectDifficultyPage() {
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mt={7}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Select a difficulty...
</Typography>
</Box>
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'row', justifyContent: 'center' }}>
<Box
component={Link}
to={'/resources/' + 'Beginner'}
sx={{
width: '280px',
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 1,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Beginner
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Know little or no SSL
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={10}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Learn basic SSL
</Typography>
</Box>
<Box
component={Link}
to={'/resources/' + 'Intermediate'}
sx={{
width: '280px',
ml: 5,
mr: 5,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Intermediate
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Know baic SSL
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={10}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Improve vocabulary & comprehesion skills
</Typography>
</Box>
<Box
component={Link}
to={'/resources/' + 'Advanced'}
sx={{
width: '280px',
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Advanced
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Can converse in SSL
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={10}
letterSpacing={0.5}
sx={{ color: '#555555', pl: 2, pr: 2 }}
>
Master advanced aspects of SSL
</Typography>
</Box>
</Box>
</Box>
)
}
import React, { useEffect } from 'react'
import { Box, Container } from '@mui/material'
import Webcam from 'react-webcam'
import axios from 'axios'
const WebcamComponent: React.FC = () => {
const webcamRef = React.useRef<Webcam>(null)
const canvasRef = React.useRef<HTMLCanvasElement>(null)
useEffect(() => {
const intervalId = setInterval(() => {
if (webcamRef.current?.video && canvasRef.current) {
const video = webcamRef.current.video
const frame = webcamRef.current.getScreenshot()
// Get Video Properties
const videoWidth = webcamRef.current.video.videoWidth
const videoHeight = webcamRef.current.video.videoHeight
// Set video width
webcamRef.current.video.width = videoWidth
webcamRef.current.video.height = videoHeight
// Set canvas height and width
const canvas = canvasRef.current
canvas.width = videoWidth
canvas.height = videoHeight
const context = canvas.getContext('2d')
if (frame && context) {
axios
.post(
'http://127.0.0.1:5000/predict',
{ frame },
{
headers: {
'Content-Type': 'application/json',
charset: 'utf-8',
},
},
)
.then((response) => {
console.log(response)
// Draw the prediction and rectangle on the canvas
canvas.width = video.videoWidth
canvas.height = video.videoHeight
context.drawImage(video, 0, 0, canvas.width, canvas.height)
context.font = '18px Arial'
if (response.data.status) {
context.fillStyle = 'green'
context.strokeStyle = 'green'
} else {
context.fillStyle = 'red'
context.strokeStyle = 'red'
}
context.fillText(`Prediction: ${response.data.prediction}`, 50, 45)
context.lineWidth = 2
context.strokeRect(50, 50, 180, 180)
})
.catch((error) => {
console.error('Error:', error)
})
}
}
}, 1000) // Adjust the interval as needed
return () => clearInterval(intervalId)
}, [])
return (
<Container maxWidth='sm'>
<Box
sx={{
position: 'relative',
width: 640,
height: 480,
}}
>
<Webcam
ref={webcamRef}
muted={true}
style={{
position: 'absolute',
width: '100%',
height: '100%',
}}
/>
<canvas
ref={canvasRef}
style={{
position: 'absolute',
width: '100%',
height: '100%',
}}
/>
</Box>
</Container>
)
}
export default WebcamComponent
type LabelMap = Record<
string,
{
name: string
color: string
}
>
const labelMap: LabelMap = {
'1': { name: 'Hello', color: 'red' },
'2': { name: 'Thank You', color: 'yellow' },
'3': { name: 'I Love You', color: 'lime' },
'4': { name: 'Yes', color: 'blue' },
'5': { name: 'No', color: 'purple' },
}
export const drawRect = (
boxes: number[][],
classes: number[],
scores: number[],
threshold: number,
imgWidth: number,
imgHeight: number,
ctx: CanvasRenderingContext2D,
): void => {
for (let i = 0; i < boxes.length; i++) {
if (boxes[i] && classes[i] && scores[i] > threshold) {
const [y, x, height, width] = boxes[i]
const text = classes[i].toString()
if (labelMap[text]) {
ctx.strokeStyle = labelMap[text].color
ctx.lineWidth = 10
ctx.fillStyle = 'white'
ctx.font = '30px Arial'
ctx.beginPath()
ctx.fillText(
`${labelMap[text].name} - ${Math.round(scores[i] * 100) / 100}`,
x * imgWidth,
y * imgHeight - 10,
)
ctx.rect(x * imgWidth, y * imgHeight, (width * imgWidth) / 2, (height * imgHeight) / 1.5)
ctx.stroke()
}
}
}
}
// // Import dependencies
// import React, { useRef, useEffect } from 'react';
// import * as tf from '@tensorflow/tfjs';
// import Webcam from 'react-webcam';
// import { Box, Container } from '@mui/material';
// // import { nextFrame } from '@tensorflow/tfjs';
// // Import drawing utility
// // import { drawRect } from './utilities';
// type DetectionResult = [tf.Tensor, tf.Tensor<tf.Rank>, tf.Tensor<tf.Rank>, tf.Tensor<tf.Rank>, tf.Tensor<tf.Rank>];
// const App: React.FC = () => {
// const webcamRef = useRef<Webcam>(null);
// const canvasRef = useRef<HTMLCanvasElement>(null);
// // Main function
// const runCoco = async () => {
// // Load network
// const net = await tf.loadGraphModel(
// 'https://hirushasign.s3.eu-north-1.amazonaws.com/model.json'
// );
// // Loop and detect hands
// setInterval(() => {
// detect(net);
// }, 16.7);
// };
// const detect = async (net: tf.GraphModel) => {
// // Check data is available
// if (
// webcamRef.current &&
// webcamRef.current.video &&
// webcamRef.current.video.readyState === 4
// ) {
// // Get Video Properties
// const video = webcamRef.current.video;
// const videoWidth = webcamRef.current.video.videoWidth;
// const videoHeight = webcamRef.current.video.videoHeight;
// // Set video width
// webcamRef.current.video.width = videoWidth;
// webcamRef.current.video.height = videoHeight;
// // Set canvas height and width
// if (canvasRef.current) {
// canvasRef.current.width = videoWidth;
// canvasRef.current.height = videoHeight;
// }
// // Make Detections
// const img = tf.browser.fromPixels(video);
// const resized = tf.image.resizeBilinear(img, [640, 480]);
// const casted = resized.cast('int32');
// const expanded = casted.expandDims(0);
// const obj = (await net.executeAsync(expanded)) as DetectionResult;
// console.log(obj)
// const boxes = await obj[1].array() as number[][];
// const classes = await obj[2].array() as number[];
// const scores = await obj[4].array() as number[];
// // Draw mesh
// if (canvasRef.current) {
// const ctx = canvasRef.current.getContext('2d');
// if (ctx) {
// requestAnimationFrame(() => {
// // drawRect(boxes[0], classes[0], scores[0], 0.8, videoWidth, videoHeight, ctx);
// });
// }
// }
// tf.dispose([img, resized, casted, expanded, obj]);
// }
// };
// useEffect(() => {
// runCoco();
// }, []);
// return (
// <Container maxWidth="sm">
// <Box
// sx={{
// position: 'relative',
// width: 640,
// height: 480,
// }}
// >
// <Webcam
// ref={webcamRef}
// muted={true}
// style={{
// position: 'absolute',
// width: '100%',
// height: '100%',
// }}
// />
// <canvas
// ref={canvasRef}
// style={{
// position: 'absolute',
// width: '100%',
// height: '100%',
// }}
// />
// </Box>
// </Container>
// );
// };
// export default App;
// interface LabelMap {
// [key: string]: {
// name: string;
// color: string;
// };
// }
// const labelMap: LabelMap = {
// '1': { name: 'Hello', color: 'red' },
// '2': { name: 'Thank You', color: 'yellow' },
// '3': { name: 'I Love You', color: 'lime' },
// '4': { name: 'Yes', color: 'blue' },
// '5': { name: 'No', color: 'purple' },
// };
// export const drawRect = (
// boxes: number[][],
// classes: number[],
// scores: number[],
// threshold: number,
// imgWidth: number,
// imgHeight: number,
// ctx: CanvasRenderingContext2D
// ): void => {
// for (let i = 0; i < boxes.length; i++) {
// if (boxes[i] && classes[i] && scores[i] > threshold) {
// const [y, x, height, width] = boxes[i];
// const text = classes[i].toString();
// if (labelMap[text]) {
// ctx.strokeStyle = labelMap[text].color;
// ctx.lineWidth = 10;
// ctx.fillStyle = 'white';
// ctx.font = '30px Arial';
// ctx.beginPath();
// ctx.fillText(`${labelMap[text].name} - ${Math.round(scores[i] * 100) / 100}`, x * imgWidth, y * imgHeight - 10);
// ctx.rect(x * imgWidth, y * imgHeight, width * imgWidth / 2, height * imgHeight / 1.5);
// ctx.stroke();
// }
// }
// }
// };
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment